Files
pos-system/services/_template_nodejs/ARCHITECTURE.en.md
Ho Ngoc Hai 4e595d0746 feat(docs): Remove outdated service templates and enhance Vietnamese architecture documentation
- Deleted obsolete service architecture templates in both English and Vietnamese to streamline content.
- Updated the Vietnamese architecture documentation with improved Mermaid diagrams for better visual clarity.
- Enhanced color coding in diagrams to improve readability and consistency across documentation.
- Added a new section detailing visual indicators for better understanding of architecture components.
2026-01-10 21:00:02 +07:00

17 KiB

Service Template Architecture

This document describes the architecture of a single microservice built from this template and how it integrates with the GoodGo microservices platform.

Overview

This template provides a complete, production-ready foundation for building individual microservices with:

  • Security: Authentication, authorization, input validation, and security headers
  • Observability: Comprehensive logging, metrics, tracing, and health checks
  • Data Management: Repository pattern, database migrations, and seeding
  • API Documentation: OpenAPI/Swagger documentation with interactive UI
  • Error Handling: Structured error responses with proper HTTP status codes
  • Docker Support: Multi-stage builds and production optimization

Important Context: This template represents a single microservice. For platform-level deployment and orchestration, services are registered in deployments/local/docker-compose.yml and routed through the Traefik API Gateway configured in infra/traefik/.


Part 1: Single Service Architecture (Internal)

This section describes the internal architecture of a single microservice built from this template.

Internal Service Components

graph TD
    Request[HTTP Request] -->|From Traefik| Middleware[Middleware Chain]
    
    subgraph SingleService[Single Service Boundary]
        Middleware --> Correlation[Correlation ID Middleware]
        Correlation --> Auth[Authentication Middleware]
        Auth --> Validation[Validation Middleware]
        Validation --> Error[Error Handler]
        Error --> Logger[Request Logger]
        Logger --> Metrics[Metrics Collector]
        
        Metrics --> Router[Router Layer]
        Router --> Controller[Controller Layer]
        Controller --> Service[Service Layer]
        Service --> Repository[Repository Layer]
        
        Repository --> Database[(PostgreSQL)]
        Service --> Cache[(Redis)]
        
        Service -.->|Health Status| Health[Health Checks]
        Service -.->|API Docs| OpenAPI[OpenAPI/Swagger]
    end
    
    Service -.->|Metrics| Prometheus[Prometheus]
    Service -.->|Traces| Jaeger[Jaeger]
    
    style Correlation fill:#e1f5fe
    style Auth fill:#f3e5f5
    style Validation fill:#e8f5e8
    style Error fill:#fff3e0
    style Logger fill:#f3e5f5
    style Metrics fill:#e8f5e8

Layer Architecture

Middleware Chain

The middleware chain processes every incoming request in order:

  1. Correlation Middleware: Generates/propagates correlation and request IDs
  2. Authentication Middleware: Validates JWT tokens (optional for public routes)
  3. Validation Middleware: Sanitizes and validates input data with Zod schemas
  4. Error Handler: Catches and formats errors into structured responses
  5. Logger Middleware: Logs request/response with correlation IDs
  6. Metrics Middleware: Collects Prometheus metrics (duration, status, payload size)

Controller Layer

  • Handles HTTP requests and responses
  • Orchestrates service layer calls
  • Formats API responses
  • Wraps async handlers for error propagation

Service Layer

  • Contains pure business logic
  • Independent of HTTP transport
  • Orchestrates repository calls
  • Implements caching strategies
  • Throws domain-specific errors

Repository Layer

  • Abstracts database operations
  • Uses Prisma ORM for type-safe queries
  • Implements repository pattern
  • Provides consistent error handling
  • Supports transactions

Request Flow

  1. Request Entry:

    • Client sends HTTP request to ingress/load balancer
    • Request includes optional correlation ID header (x-correlation-id)
  2. Correlation Middleware:

    • Generates or propagates correlation ID for request tracing
    • Adds request ID for unique request identification
    • Sets correlation headers on response
  3. Security Middleware:

    • Authentication: Validates JWT tokens (optional for public routes)
    • Authorization: Checks user roles and permissions
    • Rate Limiting: Prevents abuse with Redis-backed rate limiting
    • Helmet: Secures HTTP headers
  4. Validation Middleware:

    • Sanitizes input data (trimming, normalization)
    • Validates request data using Zod schemas
    • Returns structured validation errors
  5. Router & Controller:

    • Routes request to appropriate controller
    • Controller orchestrates business logic execution
    • Input validation and response formatting
  6. Service Layer:

    • Contains pure business logic
    • Independent of HTTP transport layer
    • Orchestrates data access and external service calls
  7. Repository Layer:

    • Implements repository pattern for data access
    • Abstracts database operations with Prisma ORM
    • Provides consistent error handling
  8. Response & Observability:

    • Formats structured JSON responses
    • Records comprehensive metrics (duration, errors, payload sizes)
    • Logs with correlation IDs for distributed tracing
    • Sends traces to Jaeger if enabled

Architecture Patterns

Repository Pattern

// Base repository with common CRUD operations
class BaseRepository<T, CreateInput, UpdateInput> {
  async findById(id: string): Promise<T | null>
  async create(data: CreateInput): Promise<T>
  async update(id: string, data: UpdateInput): Promise<T>
  // ... more common methods
}

// Specific repository extends base
class FeatureRepository extends BaseRepository<Feature, CreateFeatureInput, UpdateFeatureInput> {
  async findByName(name: string): Promise<Feature | null>
  async findByTags(tags: string[]): Promise<Feature[]>
  // ... feature-specific methods
}

Middleware Chain

// Request processing pipeline
app.use(correlationMiddleware());        // Add correlation IDs
app.use(authenticate());                 // JWT validation
app.use(authorize('admin'));             // Role checking
app.use(validateDto(schema));            // Input validation
app.use(errorHandler);                   // Error handling

Error Handling

// Custom error classes
class NotFoundError extends HttpError {
  constructor(resource: string) {
    super(`${resource} not found`, 404, 'NOT_FOUND');
  }
}

// Usage in services
if (!feature) {
  throw new NotFoundError('Feature');
}

Dependency Injection

// Constructor injection for testability
export class FeatureService {
  constructor(private repository: IRepository<Feature>) {}

  async create(data: CreateFeatureInput): Promise<Feature> {
    return this.repository.create(data);
  }
}

Best Practices

Code Organization

  • Separation of Concerns: Clear boundaries between layers (Controller → Service → Repository)
  • Single Responsibility: Each class/method has one clear purpose
  • Dependency Injection: Constructor injection for better testability
  • Error Boundaries: Proper error handling at each layer

Security

  • Input Validation: All inputs validated with Zod schemas
  • Authentication: JWT tokens with proper expiration
  • Authorization: Role-based access control (RBAC)
  • Rate Limiting: Distributed rate limiting with Redis
  • Security Headers: Helmet.js for HTTP security headers

Observability

  • Structured Logging: Consistent log format with correlation IDs
  • Metrics: Comprehensive Prometheus metrics
  • Tracing: Distributed tracing with Jaeger
  • Health Checks: Liveness and readiness probes
  • Correlation IDs: Request tracing across service boundaries

Error Handling

  • Custom Error Classes: Specific error types for different scenarios
  • HTTP Status Mapping: Proper status codes for different error types
  • Structured Responses: Consistent error response format
  • Operational Errors: Clear distinction between programming and operational errors

Testing

  • Unit Tests: Test individual functions and classes
  • Integration Tests: Test component interactions
  • E2E Tests: Test complete request/response cycles
  • Test Utilities: Shared test helpers and mocks
  • Coverage Goals: >70% code coverage target

Docker & Deployment

  • Multi-stage Builds: Optimized for production image size
  • Security: Non-root users, minimal attack surface
  • Health Checks: Container health monitoring
  • Compose Files: Development, testing, and production configurations
  • Resource Limits: Proper CPU and memory constraints

Configuration Management

Environment Variables

  • Typed Configuration: Zod schemas for env validation
  • Default Values: Sensible defaults for development
  • Override Support: .env.local overrides .env
  • Documentation: Comprehensive env variable documentation

Feature Flags

  • Runtime Configuration: Database-backed feature flags
  • Admin Control: Admin API for feature management
  • Gradual Rollout: Enable/disable features without deployment
  • Audit Trail: Track feature flag changes

API Design

RESTful Conventions

  • Resource Naming: Plural nouns for resource endpoints
  • HTTP Methods: GET, POST, PUT, DELETE, PATCH appropriately
  • Status Codes: Proper HTTP status codes for all responses
  • Content Negotiation: JSON responses with proper content-type

Response Format

{
  "success": true,
  "data": { ... },
  "message": "Operation completed successfully",
  "timestamp": "2024-01-01T00:00:00.000Z"
}

Error Responses

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": [...]
  },
  "timestamp": "2024-01-01T00:00:00.000Z"
}

Development Workflow

Local Development

  1. Setup Infrastructure: docker-compose up -d
  2. Install Dependencies: pnpm install
  3. Database Setup: pnpm prisma migrate dev && pnpm prisma db seed
  4. Start Development: pnpm dev
  5. Run Tests: pnpm test

Testing Strategy

  1. Unit Tests: Test individual functions and classes
  2. Integration Tests: Test middleware chains and service interactions
  3. E2E Tests: Test complete API workflows
  4. Performance Tests: Load testing and performance validation

Deployment Pipeline

  1. Linting: Code quality checks with ESLint and Prettier
  2. Testing: Full test suite execution (unit, integration, E2E)
  3. Security Scanning: Dependency audit, SAST, and container scanning
  4. Build: Multi-stage Docker image creation with security scanning
  5. Deploy: Container orchestration deployment with health checks
  6. Verification: Automated post-deployment health and performance verification

Part 2: Platform Integration (External)

This section describes how a service built from this template integrates with the GoodGo microservices platform.

Platform Architecture

graph TD
    Client[Client / Browser] --> Traefik[Traefik API Gateway]
    
    subgraph Platform[GoodGo Microservices Platform]
        Traefik --> AuthService[Auth Service]
        Traefik --> YourService[Your Service from Template]
        Traefik --> OtherServices[Other Services...]
        
        YourService --> SharedDB[(Shared PostgreSQL)]
        YourService --> SharedRedis[(Shared Redis)]
        
        AuthService -.->|JWT Validation| YourService
        YourService -.->|Inter-Service Calls| OtherServices
    end
    
    subgraph Observability[Observability Stack]
        Prometheus[Prometheus]
        Grafana[Grafana]
        Jaeger[Jaeger]
        Loki[Loki]
    end
    
    YourService -.->|Metrics| Prometheus
    YourService -.->|Traces| Jaeger
    YourService -.->|Logs| Loki
    Prometheus --> Grafana
    
    style Traefik fill:#ffecb3
    style YourService fill:#e1f5fe

Service Discovery & Registration

Services are registered with Traefik via Docker labels in deployments/local/docker-compose.yml:

services:
  your-service:
    build:
      context: ../..
      dockerfile: services/your-service/Dockerfile
    labels:
      # Enable Traefik for this service
      - "traefik.enable=true"
      
      # Define routing rule
      - "traefik.http.routers.your-service.rule=PathPrefix(`/api/v1/your-service`)"
      
      # Specify service port
      - "traefik.http.services.your-service.loadbalancer.server.port=5002"
      
      # Health check configuration
      - "traefik.http.services.your-service.loadbalancer.healthcheck.path=/health/live"
      - "traefik.http.services.your-service.loadbalancer.healthcheck.interval=10s"

Shared Infrastructure

Traefik API Gateway (infra/traefik/)

  • Location: infra/traefik/ - Platform-level configuration
  • Static Config: traefik.yml - Entry points, providers, API dashboard
  • Dynamic Config: dynamic/middlewares.yml, dynamic/routes.yml
  • Features: Load balancing, rate limiting, SSL/TLS, CORS, security headers

PostgreSQL Database

  • Shared or Isolated: Can be shared database with schema isolation or separate databases
  • Connection: Via DATABASE_URL environment variable
  • Migrations: Managed per-service with Prisma

Redis Cache

  • Shared Instance: Common Redis instance for all services
  • Connection: Via REDIS_URL or REDIS_HOST/REDIS_PORT
  • Use Cases: Caching, rate limiting, session storage

Observability Stack (infra/observability/)

  • Prometheus: Metrics collection from all services
  • Grafana: Visualization and dashboards
  • Jaeger: Distributed tracing
  • Loki: Log aggregation

Inter-Service Communication

HTTP/REST Communication

Services communicate via HTTP through Traefik or direct service-to-service calls:

// Example: Calling another service
const response = await fetch('http://auth-service:5001/api/v1/users/validate', {
  headers: {
    'Authorization': `Bearer ${token}`,
    'X-Correlation-ID': correlationId
  }
});

Authentication Flow

  1. Client authenticates with Auth Service
  2. Auth Service issues JWT token
  3. Client includes JWT in requests to other services
  4. Services validate JWT using @goodgo/auth-sdk
  5. Services extract user info from validated token

Part 3: Deployment Context

This section explains how to deploy a service built from this template to the platform.

Adding Service to Platform

Step 1: Create Service from Template

# Use the create-service script
./scripts/utils/create-service.sh my-new-service

# Or manually copy the template
cp -r services/_template services/my-new-service

Step 2: Register in deployments/local/docker-compose.yml

Add your service to the platform compose file:

services:
  my-new-service:
    build:
      context: ../..
      dockerfile: services/my-new-service/Dockerfile
    container_name: my-new-service-local
    environment:
      - NODE_ENV=development
      - PORT=5003
      - DATABASE_URL=${DATABASE_URL}
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - JWT_SECRET=${JWT_SECRET}
      - SERVICE_NAME=my-new-service
      - API_VERSION=v1
    depends_on:
      redis:
        condition: service_healthy
    networks:
      - microservices-network
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.my-new-service.rule=PathPrefix(`/api/v1/my-new-service`)"
      - "traefik.http.services.my-new-service.loadbalancer.server.port=5003"

Step 3: Configure Traefik Routes (Optional)

For advanced routing, add to infra/traefik/dynamic/routes.yml:

http:
  routers:
    my-new-service:
      rule: "PathPrefix(`/api/v1/my-new-service`)"
      service: my-new-service
      middlewares:
        - secure-headers
        - cors
        - compress

Step 4: Start the Platform

cd deployments/local
docker-compose up -d

Step 5: Access Your Service

Environment Configuration

Services inherit environment variables from:

  1. Platform Level: deployments/local/.env.local
  2. Service Level: Service-specific environment in docker-compose.yml
  3. Defaults: Service's .env.example for development

Operational Excellence

Incident Response

  1. Detection: Automated monitoring alerts
  2. Assessment: Incident severity classification
  3. Communication: Stakeholder notification
  4. Investigation: Root cause analysis
  5. Resolution: Fix deployment and verification
  6. Post-mortem: Incident review and improvement

Capacity Planning

  • Resource Monitoring: Track CPU, memory, disk, and network usage
  • Performance Benchmarks: Regular performance testing
  • Scaling Triggers: Automated scaling based on metrics
  • Cost Optimization: Right-sizing resources

Compliance & Security

  • Security Audits: Regular security assessments
  • Compliance Checks: GDPR, HIPAA, SOC2 compliance
  • Data Encryption: At-rest and in-transit encryption
  • Access Controls: Least privilege access principles