Overview
This document presents the architecture design for a User Service built on the AWS Serverless Framework. The service handles CRUD operations on related User and Email entities, using DynamoDB with a single-table design pattern and AWS Cognito for authentication.Architecture
System components and how they interact
Data Model
DynamoDB single-table design and access patterns
Authentication
Cognito integration and JWT token flow
API Design
Endpoints, validation, and edge cases
Key Requirements
| Requirement | Solution |
|---|---|
| Authentication | AWS Cognito with JWT tokens |
| Data Storage | DynamoDB single-table design |
| API Layer | API Gateway + Lambda |
| Inter-Service | EventBridge pub/sub |
| Infrastructure | Serverless Framework + Terraform |
Design Principles
Type Safety First
Type Safety First
Every function, handler, and data model is strongly typed. No
any types. Generics for reusable patterns. Type inference for cleaner consumer code.Single-Table DynamoDB
Single-Table DynamoDB
User and Email entities in one table. Designed for access patterns, not normalized relations. Atomic transactions where needed.
Event-Driven Communication
Event-Driven Communication
Loose coupling via EventBridge. Services react to events, not direct calls. Dead Letter Queues for failure handling.
Defense in Depth
Defense in Depth
JWT validation at API Gateway. User ID from token claims only. Rate limiting on sensitive operations.
Document Structure
| Section | What You’ll Learn |
|---|---|
| Architecture | High-level system design and component interactions |
| Data Model | DynamoDB table schema, GSIs, and access patterns |
| Authentication | Cognito setup, token flow, and authorization |
| API Design | Endpoints, request/response schemas, edge cases |
| Inter-Service | EventBridge events, consumers, failure handling |
| DevOps | CI/CD, monitoring, scaling, infrastructure as code |
| Hard Parts | Technical challenges and their solutions |
Day 1 Scope
This design is time-boxed to a single day of implementation. Below is what would be delivered versus what’s deferred.Day 1 Deliverables
- User CRUD endpoints (
/users/me) - Single primary email per user
- Cognito integration with post-confirmation trigger
- Basic EventBridge publishing (
user.created,user.deleted) - Terraform: Cognito User Pool, DynamoDB table, EventBridge bus
- Serverless Framework: Lambda handlers, API Gateway with authorizer
- Manual deployment to staging
Deferred to Future Iterations
- Multiple emails per user with verification flow
- Transactional outbox pattern (accept at-least-once initially)
- Full CI/CD pipeline with integration tests
- Comprehensive CloudWatch dashboard
- Provisioned concurrency optimization
- Admin endpoints (
GET /users/{userId})
Trade-off Rationale
| Decision | Day 1 Approach | Full Implementation | Why Defer? |
|---|---|---|---|
| Multi-email | Single email only | Full CRUD with verification | Reduces transaction complexity |
| Event delivery | Direct publish (may lose events) | Outbox pattern | Acceptable for MVP; add if reliability issues arise |
| CI/CD | Manual serverless deploy | GitHub Actions with staging/prod | Pipeline setup takes 2-3 hours |
| Monitoring | CloudWatch Logs + basic alarms | Full dashboard + X-Ray | Can add incrementally |