A deep dive into DynamoDB with Serverless API & Lambda... a severless option from aws.
View:
- Architecture,
- Design considerations,
- Security,
- Scaling,
- Patterns,
- Best practices for production or compliance-ready deployments.
1. Reference Architecture
A typical
production-ready serverless API looks like this:
Client (Web/Mobile/App)
│
▼
Amazon API
Gateway(REST or HTTP APIs)
│ AuthN/AuthZ (Cognito, JWT, IAM, Lambda Authorizers)
▼
AWS Lambda
Functions(Business Logic, Validation, Transform)
│
▼
Amazon
DynamoDB(NoSQL Database)
│
├─ DynamoDB
Streams(for
async processing, CDC events)
│ └─ Lambda / Kinesis / EventBridge → S3, Redshift, OpenSearch
│
└─ DynamoDB
TTL(auto-expiry of items, async cleanup)
2. Design Considerations
API Gateway
·
Type:
o
REST API → advanced features (usage plans, API keys,
request validation).
o
HTTP API → lower latency + cheaper, but fewer
features.
·
Throttling: Define limits per API key or client.
·
CORS: Configure properly for web apps.
AWS Lambda
- Acts as the compute glue between requests and DynamoDB.
- Keep functions stateless & idempotent.
- Cold starts: Use provisioned concurrency if latency-sensitive.
- Payload size: ≤ 6 MB via API Gateway.
DynamoDB
- Schema design is critical (partition key, sort key, GSIs).
- Single-table design is common in serverless architectures.
- On-demand vs provisioned capacity: choose based on workload patterns.
- Transactions: Use for multi-item ACID operations.
- Indexes: GSI (global secondary index) & LSI (local secondary index).
3. API Patterns for DynamoDB
CRUD
Operations
CRUD, stands for: Create, Read, Update, and Delete, … the four basic operations that can be
performed on data in a database or data management system.
It's a fundamental concept in programming and is widely used in web development and API
design.
- POST /items →
PutItem
in DynamoDB - GET /items/{id} →
GetItem
- PATCH /items/{id} →
UpdateItem
- DELETE /items/{id} →
DeleteItem
Querying
- GET /items?userId=xxx →
Query
on partition key - Search-like access → GSI with different key schema
Batch
Operations
- POST /batch →
BatchWriteItem
- GET /batch?ids=… →
BatchGetItem
Event-Driven
- DynamoDB Streams → Lambda → Notify clients (SNS/WebSocket/API callback).
- Example: Order created → Stream → Lambda → Update inventory → Publish SNS.
4. Security & Compliance
·
Authentication:
o
Cognito for user pools (OAuth2, JWT).
o
IAM for service-to-service calls.
o
Lambda authorizers for custom logic.
·
Authorization:
o
Fine-grained IAM roles for Lambda.
o
DynamoDB’s fine-grained access control (FGAC): restrict access
per item/attribute.
·
Encryption:
o
DynamoDB: Encrypted at rest by default (KMS).
o
API Gateway & Lambda: Enforce TLS 1.2+.
·
Auditing & Monitoring:
o
CloudWatch Logs, X-Ray for tracing.
o
DynamoDB Streams → Kinesis Firehose → S3 (for
audit log retention).
5. Scaling & Performance
- DynamoDB: Horizontal scaling is automatic. Watch hot partition issues (use good partition key strategy).
- Lambda: Scales concurrently (up to account limits). Use reserved concurrency to protect DynamoDB.
- API Gateway: 10,000 RPS soft limit (can be raised).
- Caching: API Gateway built-in caching or DynamoDB DAX (millisecond reads).
6. Deployment & Automation
·
Infrastructure as Code:
o
AWS SAM, CDK, Terraform, or CloudFormation.
·
CI/CD: GitHub Actions / CodePipeline → Deploy API +
Lambda + DynamoDB schema.
·
Versioning: Lambda Aliases + API Gateway stages
(dev/test/prod).
7. Example: Lambda Function (Python)
import boto3
import json
import os
dynamodb = boto3.resource(
'dynamodb')
table = dynamodb.Table(os.environ[
'twtech-TABLE_NAME'])
def
lambda_handler(
event, context):
http_method = event[
'httpMethod']
body = {}
if http_method ==
'POST':
item = json.loads(event[
'body'])
table.put_item(Item=item)
body = {
"message":
"Item created",
"item": item}
elif http_method ==
'GET':
item_id = event[
'pathParameters'][
'id']
response = table.get_item(Key={
'id': item_id})
body = response.get(
'Item', {})
elif http_method ==
'PATCH':
item_id = event[
'pathParameters'][
'id']
update = json.loads(event[
'body'])
response = table.update_item(
Key={
'id': item_id},
UpdateExpression=
"set info = :val",
ExpressionAttributeValues={
':val': update[
'info']},
ReturnValues=
"UPDATED_NEW"
)
body = response
elif http_method ==
'DELETE':
item_id = event[
'pathParameters'][
'id']
table.delete_item(Key={
'id': item_id})
body = {
"message":
"Item deleted"}
return {
"statusCode":
200,
"body": json.dumps(body)
}
8. Best Practices Checklist
- Use single-table design for complex apps.
- Apply retry with exponential backoff (Lambda → DynamoDB SDK).
- Monitor with CloudWatch Alarms (throttle events, errors, read/write capacity).
- Enable WCU/RCU auto-scaling.
- Use Dead Letter Queues (DLQs) for failed Lambda invocations.
- Minimize cold starts (use provisioned concurrency if needed).
No comments:
Post a Comment