391 lines
7.3 KiB
Markdown
391 lines
7.3 KiB
Markdown
# 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
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
```javascript
|
|
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)
|