Documentation
Engineering practices, architecture patterns, and framework-specific guides - how we design and build systems.
Engineering Practices
Introduction
Architecture Overview
Start here — the four-layer architecture, ports & adapters, and why the domain layer has zero external dependencies.
Domain-Driven Design
DDD philosophy: domain at the centre, ubiquitous language, bounded contexts, aggregates, and tactical design building blocks.
Directory Structure
The canonical folder layout for a new service — how the four layers map to real files and directories.
Architecture & Design
Hexagonal Architecture
Ports & adapters in depth — how interfaces decouple the domain from infrastructure and enable adapter swapping.
Layered Architecture
The four layers (domain, application, infrastructure, API), their responsibilities, and interaction patterns.
CQRS — Commands & Queries
Separating write operations (commands) from read operations (queries) — why this simplifies the application layer rather than adding complexity.
Exception Hierarchy
Domain, application, infrastructure, and validation exception types — how to structure and organise them.
Unit of Work Pattern
Transactional consistency across multiple repository operations using the Unit of Work pattern.
Event-Driven Patterns
Domain events, the EventPublisher port, adapter selection, and lifecycle rules.
Actor Context
Representing the authenticated caller without coupling to HTTP or JWT infrastructure.
Repository Pattern
Port-adapter repository pattern: domain interface, SQLAlchemy implementation, and domain-to-database mapping.
Security & Auth
Service Setup
Configuration & Settings
Pydantic BaseSettings, adapter switching via environment variables, and the lru_cache singleton pattern.
Dependency Injection
FastAPI's Depends() system, the DI container in api/dependencies.py, and infrastructure factory pattern.
Middleware Stack
ASGI middleware registration order, execution flow, and each layer — CORS, request context, JWT auth, logging, exception handlers.
Database Migrations
Tool-agnostic principles (source of truth, generate-then-review, naming, constraints checklist, squashing). Then: Alembic for Python services; Drizzle Kit for TypeScript/Next.js services.
Session Management
The async session factory pattern, connection pooling configuration, and session lifecycle.
API Design
Observability
Architectural Anti-Patterns
Dependency Direction Violations
How the inward dependency rule breaks in practice — and why the API layer becomes a trap for business logic.
Inter-Service Coupling
The fundamental coupling problem in layered architectures — and why the three common escape hatches each make things worse.
Business Logic in Repositories
Why business rules accumulate in the repository layer — and why this is harder to unwind than it first appears.
Infrastructure Concerns in the Business Layer
When infrastructure details leak into the application and domain layers — making business logic complex, fragile, and hard to reuse.
Kitchen Sink Services
How services grow without enforced boundaries — and why the result is untestable, high-blast-radius code no single person fully understands.
Heavy Middleware
Why the cost of middleware is multiplicative — and what belongs there versus what should be resolved on demand.
File and Media Handling
Why naive file handling exhausts memory and disk — and the streaming, size-limiting, and async patterns that avoid it.
Missing Resource Limits and Segregation
Why the absence of proactive limits makes services slower to recover — and how resource segregation protects cheap operations from expensive ones.
Frontend Patterns
React Query Patterns
Server state as single source of truth, centralised query keys, no useEffect for data fetching.
Hook Design Patterns
Source/subset hooks, mutation hooks, and optimistic updates with React Query.
Component Design
Stateless by default, container/presentational split, and composition patterns.
Context Usage
When and how to use React Context — UI state only, never server or async state.
Server vs Client Components
Decision rules for server vs client components, the providers boundary, and passing server data to client components.
API Routes & BFF Pattern
Next.js API routes as a backend-for-frontend — proxying, SSE streaming, webhook receivers, and environment variable boundaries.