Appearance
Backend Project Structure
Overview
This section explains the backend project structure following microservices architecture with standard design patterns and modern frameworks.
Architecture Pattern
Microservices Architecture
Our backend follows a microservices pattern where each service is:
- Independently deployable
- Loosely coupled
- Focused on a specific business domain
- Has its own database and API
Supported Technologies
Programming Languages
- Node.js - JavaScript/TypeScript runtime
- Go - High-performance compiled language
- Python - Versatile scripting language
Frameworks
- Hono - Fast web framework for Node.js
- Gin - HTTP web framework for Go
- FastAPI - Modern Python web framework
Project Structure
Microservices Structure
backend/
├── services/ # All microservices
│ ├── auth-service/ # Authentication service
│ │ ├── src/
│ │ │ ├── controllers/ # Request handlers
│ │ │ ├── services/ # Business logic
│ │ │ ├── models/ # Data models
│ │ │ ├── middleware/ # Custom middleware
│ │ │ ├── utils/ # Helper functions
│ │ │ └── config/ # Configuration
│ │ ├── tests/ # Test files
│ │ ├── docs/ # Service documentation
│ │ ├── Dockerfile # Container configuration
│ │ └── package.json # Dependencies (Node.js)
│ │ └── go.mod # Dependencies (Go)
│ │ └── requirements.txt # Dependencies (Python)
│ ├── user-service/ # User management service
│ ├── product-service/ # Product catalog service
│ └── order-service/ # Order processing service
├── shared/ # Shared libraries and utilities
│ ├── middleware/ # Common middleware
│ ├── utils/ # Shared utilities
│ ├── types/ # Shared type definitions
│ └── constants/ # Shared constants
├── api-gateway/ # API Gateway service
├── docker-compose.yml # Local development setup
├── kubernetes/ # K8s deployment configs
└── docs/ # API documentationDesign Patterns
Standard Patterns Implementation
1. Repository Pattern
typescript
// Node.js/TypeScript Example
interface IUserRepository {
findById(id: string): Promise<User | null>;
create(user: CreateUserDto): Promise<User>;
update(id: string, user: UpdateUserDto): Promise<User>;
delete(id: string): Promise<void>;
}
class UserRepository implements IUserRepository {
// Implementation
}2. Service Layer Pattern
go
// Go Example
type UserService struct {
repo UserRepository
}
func (s *UserService) CreateUser(ctx context.Context, user CreateUserRequest) (*User, error) {
// Business logic implementation
}3. Controller Pattern
python
# Python/FastAPI Example
@router.post("/users/", response_model=UserResponse)
async def create_user(user: CreateUserRequest, service: UserService = Depends()):
return await service.create_user(user)Exception Handling
Robust Error Handling Setup
1. Global Exception Handler
typescript
// Node.js/Hono Example
app.onError((err, c) => {
console.error(`${err}`);
if (err instanceof ValidationError) {
return c.json({ error: 'Validation failed', details: err.message }, 400);
}
if (err instanceof AuthenticationError) {
return c.json({ error: 'Authentication failed' }, 401);
}
return c.json({ error: 'Internal server error' }, 500);
});2. Custom Exception Classes
go
// Go/Gin Example
type AppError struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
func (e AppError) Error() string {
return e.Message
}3. Error Response Standardization
python
# Python/FastAPI Example
class ErrorResponse(BaseModel):
error: str
message: str
details: Optional[Dict[str, Any]] = None
timestamp: datetime = Field(default_factory=datetime.utcnow)API Documentation
OpenAPI Standard Implementation
1. OpenAPI Specification
yaml
# openapi.yaml
openapi: 3.0.0
info:
title: User Service API
version: 1.0.0
description: User management microservice
paths:
/users:
get:
summary: Get all users
responses:
'200':
description: List of users
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'2. Framework Integration
typescript
// Hono with OpenAPI
import { OpenAPIHono } from '@hono/zod-openapi'
const app = new OpenAPIHono()
app.openapi(route, handler)go
// Gin with Swagger
import "github.com/swaggo/gin-swagger"
func main() {
r := gin.Default()
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}python
# FastAPI with automatic OpenAPI generation
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI(
title="User Service",
description="User management API",
version="1.0.0"
)Service Configuration
Environment Management
bash
# .env.example
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://user:pass@localhost:5432/db
JWT_SECRET=your-secret-key
LOG_LEVEL=infoConfiguration Structure
typescript
// config/index.ts
export const config = {
app: {
port: process.env.PORT || 3000,
env: process.env.NODE_ENV || 'development',
},
database: {
url: process.env.DATABASE_URL,
},
auth: {
jwtSecret: process.env.JWT_SECRET,
},
}Testing Structure
Test Organization
tests/
├── unit/ # Unit tests
├── integration/ # Integration tests
├── e2e/ # End-to-end tests
├── fixtures/ # Test data
└── mocks/ # Mock objectsTesting Standards
- Minimum 80% code coverage
- Unit tests for all business logic
- Integration tests for API endpoints
- E2E tests for critical user flows
Deployment
Containerization
dockerfile
# Dockerfile example
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]Kubernetes Deployment
yaml
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 3000Best Practices
Code Organization
- Separation of Concerns: Keep controllers, services, and repositories separate
- Dependency Injection: Use DI containers for better testability
- Configuration Management: Centralize configuration with environment variables
- Logging: Implement structured logging with appropriate levels
- Monitoring: Add health checks and metrics endpoints
Security
- Input Validation: Validate all inputs using schemas
- Authentication: Implement JWT or OAuth2
- Authorization: Use role-based access control
- Rate Limiting: Implement API rate limiting
- CORS: Configure CORS properly for web clients