Skip to content

Framework Architecture ​

Understanding the goserve framework architecture and design patterns.

Overview ​

goserve is built on a feature-based architecture that promotes clean code, separation of concerns, and testability. The framework emphasizes each API being independent while sharing common services, reducing code conflicts in team environments.

It provides a recipe for building scalable RESTful APIs with built-in support to integrate for authentication, authorization, caching, and database interactions.

Core Principles ​

  1. Feature Independence - Each API feature is organized in separate directories by endpoint
  2. Service Sharing - Common services can be shared across features while maintaining independence
  3. Layered Architecture - Clear separation between Controllers, Services, Models, and DTOs
  4. Testability - Architecture supports easy unit and integration testing
  5. Scalable Architecture - Modular design supports scaling and extension
  6. Authentication & Authorization - Built-in patterns for JWT and API key auth

Framework Code Organization ​

.
β”œβ”€β”€ dto                      # Data Transfer Objects (input/output structs)
β”‚   β”œβ”€β”€ mongoid.go           # Mongo ID helper for DTOs
β”‚   β”œβ”€β”€ pagination.go        # Pagination DTO fields
β”‚   β”œβ”€β”€ slug.go              # Slug generation DTO helper
β”‚   └── uuid.go              # UUID handling
β”‚
β”œβ”€β”€ micro                    # Microservice-oriented code
β”‚   β”œβ”€β”€ controller.go        # Microcontroller logic base
β”‚   β”œβ”€β”€ interfaces.go        # Interfaces for micro handlers
β”‚   β”œβ”€β”€ message.go           # Microservice message types
β”‚   β”œβ”€β”€ nats.go              # NATS integration helpers
β”‚   β”œβ”€β”€ request.go           # Microrequest helpers
β”‚   β”œβ”€β”€ router.go            # Router setup for microservices
β”‚   └── sender.go            # Client code to send micro messages
β”‚
β”œβ”€β”€ middleware               # Request/response middleware
β”‚   β”œβ”€β”€ errorcatcher.go      # Panic/recover middleware
β”‚   └── notfound.go          # β€œ404 not found” handler
β”‚
β”œβ”€β”€ mongo                    # Mongo database helpers
β”‚   β”œβ”€β”€ builder.go           # Query builder utilities
β”‚   β”œβ”€β”€ database.go          # DB connection & pooling
β”‚   β”œβ”€β”€ query.go             # Generic query helpers
β”‚   └── validation.go        # Mongo validation logic
β”‚
β”œβ”€β”€ postgres                 # Postgres database helpers (if used)
β”‚   └── database.go          # Postgres DB connection logic
β”‚
β”œβ”€β”€ network                  # HTTP API layer utilities
β”‚   β”œβ”€β”€ apierror.go          # Standard API error structs
β”‚   β”œβ”€β”€ controller.go        # HTTP controller base
β”‚   β”œβ”€β”€ header.go            # Header helpers
β”‚   β”œβ”€β”€ interfaces.go        # HTTP interfaces (controllers, services)
β”‚   β”œβ”€β”€ parsers.go           # Request parsing helpers
β”‚   β”œβ”€β”€ request.go           # HTTP request helpers
β”‚   β”œβ”€β”€ response.go          # HTTP response helpers
β”‚   β”œβ”€β”€ router.go            # Route registration
β”‚   β”œβ”€β”€ sender.go            # HTTP client helpers
β”‚   └── validation.go        # HTTP request validation
β”‚
β”œβ”€β”€ redis                   # Redis caching helpers
β”‚   β”œβ”€β”€ cache.go            # High-level cache API
β”‚   └── store.go            # Redis connection & operations
β”‚
└── utility                 # Generic helpers
    β”œβ”€β”€ format.go           # Data formatting utilities
    β”œβ”€β”€ mapper.go           # Struct mapping helpers
    └── random.go           # Random value helpers

Layered Architecture Pattern ​

goserve follows a 4-layer architecture pattern that separates concerns while maintaining clean dependencies:

1. Controller Layer (Network Layer) ​

Handles HTTP requests and responses, acts as the entry point:

Location: api/[feature]/controller.go

Responsibilities:

  • Route definition and mounting
  • Request parsing and validation
  • Authentication and authorization checks
  • Calling service layer methods
  • Response formatting
  • HTTP-specific logic handling
  • Error response formatting

Key Pattern:

go
type controller struct {
    network.Controller
		// Other dependencies...
}

func NewController(
	authProvider network.AuthenticationProvider,
	authorizeProvider network.AuthorizationProvider,
	// Other dependencies...
) network.Controller {
	return &controller{
		Controller: network.NewController("/auth", authProvider, authorizeProvider),
		// Initialize other dependencies...
	}
}

func (c *controller) MountRoutes(group *gin.RouterGroup) {
	group.DELETE("/signout", c.Authentication(), c.signOutBasic)
}

func (c *controller) signOutBasic(ctx *gin.Context) {
	// Parse request
	// Call service method
	// Format response
}

2. Service Layer (Business Logic) ​

Contains business logic and database interactions:

Location: api/[feature]/service.go

Responsibilities:

  • Business rule enforcement
  • Data transformation and validation
  • Database operations coordination
  • Cache management
  • External service integration

Key Pattern:

go
type Service interface {
	CreateBlog(d *dto.CreateBlog) (*model.Blog, error)
		// Other service methods...
}

type service struct {
    db postgres.Database,
    cache redis.Cache[dto.BlogPublic],
}

func NewService(db postgres.Database) Service {
	return &service{
		db: db,
	}
}

func (s *service) CreateBlog(dto *dto.CreateBlog) (*dto.BlogPublic, error) {
    // Business logic validation
    // Database operations
    // Cache invalidation
    // Return result
}

3. Model Layer (Data Entities) ​

Defines database schema and internal data structures:

Location: api/[feature]/model/[record].go

Responsibilities:

  • Database table representation
  • Data type definitions
  • Field mapping documentation
  • Internal domain entities

Key Pattern:

go
type Blog struct {
    ID          uuid.UUID   // id
    Title       string      // title
    Description string      // description
    Text        *string     // text
    AuthorID    uuid.UUID   // author_id
    Status      bool        // status
    CreatedAt   time.Time   // created_at
    UpdatedAt   time.Time   // updated_at
}

4. DTO Layer (Data Transfer Objects) ​

Defines request/response contracts and API boundaries:

Location: api/[feature]/dto/[operation].go

Responsibilities:

  • Input validation and sanitization
  • Output formatting and filtering
  • API contract documentation
  • Sensitive data hiding

Key Pattern:

go
type BlogCreate struct {
    Title       string   `json:"title" validate:"required,min=3,max=500"`
    Description string   `json:"description" validate:"required,min=3,max=2000"`
    DraftText   string   `json:"draftText" validate:"required,max=50000"`
    Tags        []string `json:"tags" validate:"required,min=1,dive,uppercase"`
}

type BlogPublic struct {
    ID          uuid.UUID  `json:"id"`
    Title       string     `json:"title"`
    Description string     `json:"description"`
    Tags        []string   `json:"tags"`
    Author      *UserInfo  `json:"author"`
    PublishedAt time.Time  `json:"publishedAt"`
}

Recommended implementation patterns for building APIs with goserve for a production-ready architecture.

Complete Request Lifecycle ​

HTTP Request
    ↓
Root Middleware (Global)
β”œβ”€β”€ Error Catcher
β”œβ”€β”€ API Key Authentication
└── Not Found Handler
    ↓
Router (Gin)
    ↓
Feature Route Group (/api/blog)
    ↓
Authentication Middleware (JWT)
β”œβ”€β”€ Extract Bearer Token
β”œβ”€β”€ Verify RSA Signature
β”œβ”€β”€ Validate Claims & Expiry
β”œβ”€β”€ Load User from Database
└── Set User Context
    ↓
Authorization Middleware (Roles)
β”œβ”€β”€ Check User Permissions
β”œβ”€β”€ Validate Required Roles
└── Allow/Deny Access
    ↓
Controller Handler
β”œβ”€β”€ Parse Request Body (DTO)
β”œβ”€β”€ Validate Input
└── Call Service Method
    ↓
Service Layer (Business Logic)
β”œβ”€β”€ Business Rule Validation
β”œβ”€β”€ Database Operations
β”œβ”€β”€ Cache Management
└── External Service Calls
    ↓
Controller Handler
    ↓
Response Formatting
β”œβ”€β”€ Success (200-299)
β”œβ”€β”€ Client Error (400-499)
└── Server Error (500-599)

Middleware Chain Details ​

Authentication Middleware (protected routes):

  • JWT token extraction and validation
  • User context loading

Authorization Middleware (role-protected routes):

  • Permission checking
  • Role validation
  • Access control

Feature-Based Organization ​

goserve organizes code by business features rather than technical layers, making it easier for teams to work independently:

Feature Organization Principles ​

Independent Features: Each feature is self-contained with its own directory:

api/auth/     # Complete auth feature
api/blog/     # Blog management feature

Shared Resources: Related features can share models and DTOs:

api/blog/
β”œβ”€β”€ dto/       # Shared between author/editor features
β”œβ”€β”€ model/     # Shared database models
└── service.go # Shared business logic

Clear Boundaries: Features communicate through well-defined interfaces, not direct dependencies.

Dependency Injection & Module System ​

goserve uses a module-based dependency injection system that wires all components together:

Module Pattern ​

The module interface enables clean dependency injection:

go
type Module interface {
    GetInstance() *module
    Controllers() []network.Controller
    RootMiddlewares() []network.RootMiddleware
    AuthenticationProvider() network.AuthenticationProvider
    AuthorizationProvider() network.AuthorizationProvider
}

Benefits ​

  • Clean Architecture: Clear component relationships
  • Testability: Easy mocking of dependencies
  • Flexibility: Easy to swap implementations
  • Maintainability: Centralized dependency management

Error Handling ​

Consistent error handling across the framework:

  • Structured error responses
  • HTTP status code mapping
  • Error logging and tracking

Configuration Management ​

Environment-based configuration:

  • Environment variables
  • Configuration files
  • Default values
  • Type-safe config access

Testing Support ​

Built-in support for testing:

  • Test server utilities
  • Mock generators
  • Integration test helpers

Microservices Support ​

goserve's modular architecture supports scaling to larger applications through service extraction and component reuse.

Performance Considerations ​

  • Connection Pooling: Optimized database connections
  • Caching Strategy: Redis integration with cache-aside pattern
  • Efficient Routing: Gin-based routing with minimal overhead
  • Horizontal Scaling: Stateless services ready for scaling

Testing Architecture ​

goserve supports comprehensive testing at all levels:

Released under the Apache 2.0 License