Serverless REST API#
A fully serverless REST API using API Gateway, Lambda, DynamoDB, and Cognito — perfect for modern application backends with variable traffic patterns.
Architecture Overview#
┌─────────────────────────────────────┐
│ CloudFront (CDN) │
│ API Gateway (REST) │
│ │ │
│ ┌─────────┴─────────┐ │
│ │ WAF (rate-limit) │ │
│ └─────────┬─────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ Cognito (Auth) │ │
│ └─────────┬─────────┘ │
│ │ │
│ ┌─────────▼─────────┐ │
│ │ Lambda Functions │ │
│ │ /users, /orders, │ │
│ │ /products │ │
│ └──┬──────┬──────┬──┘ │
│ │ │ │ │
│ ┌────▼──┐ ┌─▼───┐ ┌▼────┐ │
│ │DynamoDB│ │SQS │ │S3 │ │
│ │(users)│ │(orders)│ │(assets)│ │
│ └───────┘ └─────┘ └─────┘ │
└─────────────────────────────────────┘Services Used#
| Service | Purpose | Configuration |
|---|---|---|
| API Gateway (REST) | HTTP API endpoint | Usage plans, API keys, throttling, caching |
| Lambda | Business logic | Node.js 20, 512MB, 30s timeout, reserved concurrency |
| DynamoDB | Primary database | On-demand capacity, DAX for caching, TTL for sessions |
| Cognito | User authentication | User pools, OAuth 2.0, social identity providers |
| SQS | Async order processing | FIFO queue (exactly-once), DLQ for failures |
| S3 | File uploads & static assets | Presigned URLs for uploads, static website hosting |
| CloudFront | CDN + API caching | Custom domain, HTTPS, WAF integration |
| WAF | Security | Rate limiting (1000 req/min per IP), bot control |
Key Design Decisions#
| Decision | Rationale |
|---|---|
| Lambda over ECS/Fargate | Variable traffic, infrequent usage, no need to manage servers |
| DynamoDB over RDS | Serverless, auto-scaling, single-digit ms latency, pay-per-request |
| SQS FIFO for orders | Exactly-once processing, message ordering guaranteed |
| Cognito over custom auth | Managed identity, social login, MFA, no password hashing |
| Presigned S3 URLs | Direct client-to-S3 uploads without Lambda processing |
| Reserved concurrency | Prevents thundering herd from overwhelming downstream resources |
Real-World Use Case#
Scenario: A mobile app backend for a food delivery service with 50K users.
How this architecture handles it:
- User signup: Cognito handles registration, MFA, social login (Google/Apple)
- Browse restaurants: API Gateway cache + DynamoDB DAX serve menu data at <5ms
- Place order: API → Lambda → SQS FIFO (ensures order sequencing)
- Payment processing: Separate Lambda with reserved concurrency of 5
- Order status updates: DynamoDB Stream → Lambda → push notification via SNS
- Peak lunch hour: DynamoDB auto-scales, Lambda concurs to hundreds of instances
Lambda Function Examples#
# Get product listing
def get_products(event, context):
table = boto3.resource('dynamodb').Table('Products')
response = table.scan()
return {'statusCode': 200, 'body': json.dumps(response['Items']), 'headers': {'Content-Type': 'application/json'}
}
# Process order (SQS trigger)
def process_order(event, context):
for record in event['Records']:
order = json.loads(record['body'])
validate_payment(order)
update_inventory(order)
notify_restaurant(order)
notify_customer(order)Cost Estimate (Monthly)#
| Service | Estimated Cost |
|---|---|
| Lambda (1M invocations) | ~$2 |
| API Gateway (10M requests) | ~$35 |
| DynamoDB (on-demand) | ~$50 |
| Cognito (50K MAU) | ~$0 (free tier) |
| SQS (1M requests) | ~$0.04 |
| S3 | ~$5 |
| Total | ~$92/month |
✅ Key Exam Takeaways#
- Lambda + API Gateway = core serverless pattern for the exam
- DynamoDB is serverless — no need to provision, it scales automatically
- Reserved concurrency prevents one function from consuming all Lambda capacity
- SQS FIFO for exactly-once processing with ordering
- Presigned URLs allow direct S3 uploads without Lambda processing
- Cognito handles authentication — never build your own auth system