Files
2025-11-30 09:05:07 +08:00

7.3 KiB

Serverless Architecture Patterns

Table of Contents

  • Core Concepts
  • Function Patterns
  • Data Patterns
  • Integration Patterns
  • Best Practices

Core Concepts

Function as a Service (FaaS)

Code runs in response to events without managing servers.

Key Characteristics:

  • Event-driven execution
  • Automatic scaling
  • Pay-per-execution pricing
  • Stateless functions
  • Short-lived execution

Major Providers:

  • AWS Lambda
  • Google Cloud Functions
  • Azure Functions
  • Cloudflare Workers

Backend as a Service (BaaS)

Managed services replace traditional backend components.

Examples:

  • Database: DynamoDB, Firestore, Fauna
  • Auth: Auth0, AWS Cognito, Firebase Auth
  • Storage: S3, Cloud Storage
  • APIs: API Gateway, AppSync

Function Patterns

API Endpoint Pattern

API Gateway --trigger--> Lambda Function --response--> API Gateway

Use case: REST API, GraphQL API

Example (AWS):

API Gateway (POST /users)
    ↓
Lambda (createUser)
    ↓
DynamoDB

Event Processing Pattern

Event Source --event--> Lambda --process--> Output

Event Sources:

  • S3: File uploads
  • DynamoDB Streams: Database changes
  • SQS: Message queue
  • SNS: Notifications
  • EventBridge: Custom events

Use case: Image processing, data transformation, ETL

Scheduled Jobs Pattern

CloudWatch Events (cron) --trigger--> Lambda

Use case: Batch processing, cleanup jobs, reports

Example:

EventBridge Rule (rate(1 day))
    ↓
Lambda (dailyReport)
    ↓
Send Email / Store Results

Stream Processing Pattern

Kinesis Stream --records--> Lambda --aggregate/transform-->  Destination

Use case: Real-time analytics, log processing

Data Patterns

DynamoDB Pattern (NoSQL)

Access Patterns:

  • Single table design
  • GSI for query flexibility
  • DynamoDB Streams for CDC

Best practices:

  • Design for access patterns first
  • Use partition keys for distribution
  • Batch operations when possible
  • Enable auto-scaling

Aurora Serverless Pattern (SQL)

Features:

  • Auto-scaling SQL database
  • Pay per use
  • Data API for HTTP access

Use case: Variable workloads, development environments

Multi-Database Pattern

Polyglot persistence:

  • DynamoDB for user profiles
  • S3 for files
  • ElastiCache for sessions
  • RDS for relational data

API Composition Pattern

Function aggregates data from multiple sources:

Lambda
    ├── Call Service A API
    ├── Call Service B API
    ├── Query DynamoDB
    └── Aggregate results

Integration Patterns

API Gateway Integration

Types:

  • Lambda Proxy: Full HTTP request to function
  • Lambda Integration: Custom request/response mapping
  • HTTP Proxy: Direct passthrough to backend
  • Mock: Return static response

Features:

  • Request validation
  • Authorization
  • Rate limiting
  • Caching
  • CORS

EventBridge Pattern

Central event bus for service integration:

Service A --event--> EventBridge --route--> Lambda B
                                    --route--> Lambda C
                                    --route--> SQS Queue

Use case: Event-driven architecture, decoupling services

Step Functions Pattern

Orchestrate multiple Lambda functions:

Step Functions State Machine
    ↓
Step 1: Validate (Lambda)
    ↓
Step 2: Process (Lambda)
    ↓
Step 3: Notify (Lambda)

Use case: Workflows, long-running processes, error handling

SQS Queue Pattern

Decouple and buffer workloads:

Producer --message--> SQS Queue --poll--> Lambda Consumer

Benefits:

  • Async processing
  • Rate limiting
  • Retry logic
  • Dead letter queue

Fan-out Pattern

Single event triggers multiple functions:

S3 Upload Event
    ↓
SNS Topic
    ├── Lambda: Create Thumbnail
    ├── Lambda: Extract Metadata
    └── Lambda: Virus Scan

Best Practices

Cold Start Optimization

Strategies:

  • Keep functions small
  • Minimize dependencies
  • Use provisioned concurrency (critical paths)
  • Reuse connections
  • Initialize outside handler
// Good: Initialize outside
const db = new DynamoDB.DocumentClient();

exports.handler = async (event) => {
    // Use db here
};

Error Handling

Patterns:

  • Return errors explicitly
  • Use Dead Letter Queues
  • Implement retry logic
  • Log errors with context
exports.handler = async (event) => {
    try {
        // Process event
    } catch (error) {
        console.error('Error:', error);
        // Send to DLQ or SNS
        throw error; // Trigger retry
    }
};

Security

Best practices:

  • Least privilege IAM roles
  • Encrypt environment variables
  • Use VPC for private resources
  • Validate input
  • Use AWS Secrets Manager

Cost Optimization

Strategies:

  • Right-size memory (affects CPU)
  • Optimize execution time
  • Use SQS for buffering
  • Set appropriate timeouts
  • Monitor unused functions

Observability

Logging:

  • Use structured logging (JSON)
  • Include correlation IDs
  • Log key metrics

Monitoring:

  • CloudWatch Metrics
  • X-Ray for tracing
  • Custom metrics

Alerts:

  • Error rates
  • Duration
  • Throttles
  • Dead letter queue depth

State Management

Stateless functions:

  • No local state
  • Use external stores (DynamoDB, S3, ElastiCache)
  • Pass state in events

Step Functions for stateful workflows:

  • Maintain workflow state
  • Handle long-running processes

Testing

Levels:

  • Unit: Test handler logic
  • Integration: Test with local services (LocalStack)
  • E2E: Test in AWS

Tools:

  • Jest/Mocha for unit tests
  • AWS SAM for local testing
  • LocalStack for local AWS

Deployment

IaC Tools:

  • AWS SAM (Serverless Application Model)
  • Serverless Framework
  • AWS CDK
  • Terraform

CI/CD:

  • Automated testing
  • Canary deployments
  • Blue-green deployments
  • Rollback capability

Architecture Examples

REST API

API Gateway (REST)
    ├── GET /items --> Lambda (listItems) --> DynamoDB
    ├── POST /items --> Lambda (createItem) --> DynamoDB
    └── GET /items/{id} --> Lambda (getItem) --> DynamoDB

Event-Driven Processing

S3 Bucket (image upload)
    ↓
Lambda (processImage)
    ├── Resize image
    ├── Store in S3
    └── Update DynamoDB

Microservices

Service 1: API Gateway + Lambda + DynamoDB
Service 2: API Gateway + Lambda + RDS Aurora
Service 3: EventBridge + Lambda + SQS

Inter-service: HTTP APIs or EventBridge

Data Pipeline

S3 (raw data)
    ↓
Lambda (transform)
    ↓
Kinesis Firehose
    ↓
S3 (processed data)
    ↓
Athena (query)

Common Challenges

Vendor Lock-in

Mitigation: Use frameworks (Serverless Framework), abstract provider-specific code

Cold Starts

Mitigation: Provisioned concurrency, keep functions warm, optimize bundle size

Debugging

Mitigation: Structured logging, X-Ray tracing, local testing

Testing

Mitigation: Unit tests, integration tests with LocalStack, E2E tests in staging

Distributed Tracing

Mitigation: AWS X-Ray, correlation IDs, structured logs

When to Use Serverless

Good for:

  • Variable workload
  • Event-driven applications
  • APIs with unpredictable traffic
  • Scheduled jobs
  • Rapid prototyping
  • Startups (reduce ops overhead)

Not ideal for:

  • Long-running processes (>15 min)
  • Consistent high-throughput
  • Applications requiring low latency
  • Complex state management
  • Heavy computation (cost)