Skip to Content
Engineering11 Documentation 🔥
BackendArchitecture

Backend Architecture

Foundation backends are cloud-native, event-driven, and designed for scale from day one.

Architectural Patterns

Microservices Architecture

Engineering11 uses a microservices architecture with clear domain boundaries:

Core Principles:

  • Domain-driven design - Each service owns a specific business domain
  • Independent deployment - Services deploy independently without coordination
  • Autonomous scaling - Services scale based on their own demand patterns
  • Clear contracts - Well-defined APIs and event schemas between services

Benefits:

  • Teams can work independently without blocking each other
  • Failures are isolated to specific domains
  • New features don’t require refactoring the entire system
  • Services use the most appropriate data store for their domain

Event-Driven Workflows

Engineering11 embraces event-driven architecture for async communication:

Pub/Sub Messaging:

  • Services publish domain events to Pub/Sub topics
  • Consumers subscribe to relevant events
  • Decoupled producers and consumers
  • Natural fit for AI enrichment pipelines

Event Flow:

Service A → Publish Event → Pub/Sub Topic → Multiple Subscribers ├→ Service B (enrichment) ├→ Service C (analytics) └→ Service D (notifications)

Benefits:

  • Loose coupling between services
  • Easy to add new event consumers
  • Natural backpressure and retry mechanisms
  • AI and automation added without blocking user flows

Repository Pattern

All data access goes through repository classes that abstract storage implementations:

Abstraction Benefits:

  • Business logic doesn’t depend on storage details
  • Easy to swap data stores (Firestore → SQL)
  • Simplified testing with mock repositories
  • Consistent patterns across all services

Common Repositories:

  • CollectionRepository<T> - Document/collection-based storage
  • SubcollectionRepository<T, P> - Nested collections
  • SqlRepository<T> - SQL-based storage
  • Custom repositories for specific query patterns

See Repository Examples →

Multi-Tenancy

Data isolation is built into every layer of the architecture:

Tenant Context:

  • Every request carries tenant/customer context
  • Repositories filter data by tenant automatically
  • Cross-tenant data access is explicitly prevented
  • Audit logs capture tenant information

Isolation Strategies:

  • Logical partitioning in shared databases
  • Separate database instances for enterprise customers
  • Row-level security in Cloud SQL
  • Document-level filtering in Firestore

White-Label Support:

  • Custom domains per tenant
  • Tenant-specific configuration
  • Branding and theme customization
  • Feature flags per tenant

API-First Design

All services expose well-documented, versioned APIs:

REST APIs:

  • OpenAPI/Swagger documentation
  • Versioned endpoints (/v1/, /v2/)
  • Generated TypeScript clients
  • Standard error responses

IPC (Inter-Process Communication):

  • Service-to-service REST endpoints
  • Authenticated via Google IAM
  • Used for synchronous operations
  • Circuit breakers and retries built in

Server APIs (Packages):

  • Published npm packages
  • Shared domain models and types
  • Repository-based data access
  • Business logic services
  • Consumed by other backend services

Explore Server API Packages →


Service Anatomy

Every Foundation microservice follows the same structured parts:

Server API Part

Published as an npm package (e.g., @engineering11/user-api):

Contents:

  • Domain models and interfaces
  • Repository classes for data access
  • Business logic services
  • Constants (collections, topics, permissions)
  • Shared utilities

Used By:

  • Other backend services that need this domain’s data or logic
  • Ensures type safety and consistent behavior
  • Versioned for backward compatibility

REST Part

Client-facing HTTP endpoints:

Responsibilities:

  • Expose domain functionality to frontend apps
  • Request validation using DTOs
  • Authentication and authorization
  • Rate limiting and throttling

Technology:

  • NestJS framework
  • Express HTTP server
  • JWT authentication
  • OpenAPI documentation

IPC REST Part

Service-to-service communication endpoints:

Responsibilities:

  • Internal APIs for backend coordination
  • Not exposed to external clients
  • Authenticated via Google IAM
  • Used for synchronous workflows

Tasks Part

Asynchronous event processing:

CQRS Pattern:

  • Event receivers (controllers)
  • Event definitions
  • Command definitions
  • Command handlers
  • Sagas (event → command mapping)

Use Cases:

  • Process background workflows
  • React to domain events from other services
  • Enrich data asynchronously
  • Trigger AI pipelines

See CQRS Implementation →

Functions Part

Cloud Functions triggered by events:

Triggers:

  • Firestore document changes
  • Cloud Storage uploads
  • Pub/Sub messages
  • HTTP requests

Use Cases:

  • Real-time data transformations
  • Lightweight event handling
  • Third-party webhooks
  • Scheduled lightweight tasks

Jobs Part

Scheduled and recurring background jobs:

Technology:

  • Cloud Scheduler triggers
  • Background job queues
  • Configurable schedules (cron expressions)

Use Cases:

  • Daily data exports
  • Periodic cleanup tasks
  • Report generation
  • Batch processing

Migrations Part

Database schema and data evolution:

Strategy:

  • Version-controlled migration scripts
  • Run once per environment
  • Idempotent where possible
  • Rollback scripts for critical changes

Types:

  • Schema migrations (add/modify fields)
  • Data migrations (backfill, transform)
  • Index creation
  • Security rules updates

Technology Stack

Backend Technologies

Runtime & Language:

  • Node.js
  • TypeScript for type safety
  • ES Modules

Framework:

  • NestJS for REST APIs and dependency injection
  • Express as HTTP server
  • CQRS module for event-driven workflows

Data Stores:

  • Firestore for document storage
  • SQL for relational data
  • Redis for caching and sessions
  • Cloud Storage for files

Messaging & Events:

  • Google Pub/Sub for async messaging
  • Cloud Tasks for queued workflows
  • Cloud Scheduler for cron jobs

Authentication & Security:

  • Google Identity Platform
  • JWT tokens
  • Google IAM for service-to-service auth
  • Cloud Secret Manager for secrets

Modern Development Tooling

Engineering11 systems use modern tooling to improve the developer experience:

Monorepo Management:

  • Yarn workspaces for dependency management
  • Nx for build orchestration and caching
  • Release Please for automated versioning and changelogs

Quality & Testing:

  • Jest for unit and integration tests
  • Supertest for API testing
  • gts (Google TypeScript Style) for linting and formatting
  • Husky + lint-staged for pre-commit hooks
  • Commitlint for conventional commits

Development Environment:

  • Docker for containerization
  • Docker Compose for local orchestration
  • Hot reload for rapid iteration

Infrastructure

Cloud Platform:

  • Google Cloud Platform (GCP)
  • Cloud Run for container deployment
  • Kubernetes Engine for advanced orchestration

Deployment:

  • Terraform for Infrastructure as Code
  • Cloud Build for CI/CD pipelines
  • Multi-environment strategy (dev, CI, QA, stage, prod)

Observability:

  • Cloud Logging (structured logs)
  • Cloud Monitoring (metrics and alerting)
  • Cloud Trace (distributed tracing)
  • Error Reporting for exception tracking

Operational Patterns

Deployment Pipeline

Code Push → Cloud Build ↓ Run Tests & Linters ↓ Build Docker Image ↓ Push to Container Registry ↓ Deploy to Environment ↓ Health Checks ↓ Rollback on Failure

Environment Strategy

Development (dev):

  • Rapid iteration
  • Frequent deployments
  • Shared by all engineers

Continuous Integration (CI):

  • Automated testing environment
  • Triggered by pull requests
  • Validates changes before merge

Quality Assurance (QA):

  • Manual and automated testing
  • Stable, pre-production environment
  • Customer demo and UAT

Staging (stage):

  • Production mirror
  • Final validation before release
  • Performance and load testing

Production (prod):

  • Live customer environment
  • Automated deployments with approval gates
  • Blue-green or canary deployments

Observability & Monitoring

Structured Logging:

  • JSON formatted logs
  • Correlation IDs for request tracing
  • Tenant and user context in all logs
  • Severity levels (debug, info, warn, error)

Metrics:

  • Request latency and throughput
  • Error rates and types
  • Resource utilization (CPU, memory)
  • Business metrics (signups, revenue)

Alerting:

  • Error rate thresholds
  • Latency SLOs
  • Resource exhaustion
  • Integration with PagerDuty/Slack

Distributed Tracing:

  • Request flow across services
  • Performance bottleneck identification
  • Dependency mapping
  • Latency analysis

Resilience & Reliability

Circuit Breakers:

  • Prevent cascading failures
  • Fail fast when dependencies are down
  • Automatic recovery when service stabilizes

Retry Logic:

  • Exponential backoff
  • Jittered retries to prevent thundering herd
  • Maximum retry limits
  • Idempotent operations

Health Checks:

  • Liveness probes (is service running?)
  • Readiness probes (is service ready for traffic?)
  • Dependency health checks
  • Graceful shutdown

Rate Limiting:

  • Per-user rate limits
  • Per-tenant quotas
  • Burst allowances
  • 429 responses with retry-after headers

Design Principles

1. Consistency Over Flexibility

All services follow the same patterns:

  • Same project structure
  • Same naming conventions
  • Same deployment workflows
  • Same observability patterns

Result: Lower cognitive load, faster onboarding, easier maintenance.

2. Explicit Over Implicit

  • Clear, well-defined contracts between services
  • Explicit error handling
  • Type safety through TypeScript
  • Documented assumptions

Result: Fewer bugs, easier debugging, better collaboration.

3. Async Over Sync

  • Prefer async workflows for non-critical paths
  • Events for cross-service communication
  • Background jobs for heavy processing
  • Avoid blocking user requests

Result: Better scalability, natural AI integration, improved UX.

4. Secure by Default

  • Authentication required unless explicitly public
  • Tenant isolation at every layer
  • Secrets in Secret Manager, never in code
  • Principle of least privilege for IAM

Result: Reduced security risk, compliance-ready, customer trust.


Next Steps

Last updated on