This is a reference architecture for a multi-tenant SaaS application built on the AWS serverless technology stack. The project demonstrates how to implement a scalable, secure, and cost-effective SaaS solution on the AWS cloud platform, supporting multiple tenant isolation models (pooled and silo).
This project is derived from the official AWS AWS Serverless SaaS Workshop (based on its Lab6), and builds on it with extensive changes including backend architecture refactoring, data model simplification, runtime and dependency upgrades, and deployment script enhancements. It now evolves as an independent derivative project under MIT-0.
- Full list of differences and their rationale:
docs/CHANGES_FROM_WORKSHOP.md - Copyright provenance and attribution:
NOTICE| License:LICENSE(MIT-0)
- Multi-tenant architecture: Supports both pooled and silo tenant isolation models
- Tiered services: Supports four service tiers — Basic, Standard, Premium, and Platinum
- Serverless architecture: Built on serverless services such as AWS Lambda, API Gateway, and DynamoDB
- Identity authentication: Integrates AWS Cognito for user identity management
- API throttling: Tier-based API usage control
- Monitoring and logging: Integrates CloudWatch and X-Ray for application monitoring
- Automated deployment: Uses AWS SAM and CDK for infrastructure as code
- AWS Lambda: Serverless compute service
- API Gateway: RESTful API management and routing
- DynamoDB: NoSQL database storage
- AWS Cognito: User identity authentication and authorization
- CloudFormation/SAM: Infrastructure as code
- Python 3.13: Backend development language
- PyJWT[crypto]: Cognito JWT validation (replaces the unmaintained
python-jose, avoiding CVE-2024-33663/33664)
Based on AWS's officially recommended best practices, this project adopts a simplified partition-key design and removes the complex sharding strategy to improve performance and reduce cost.
- Even distribution: Use the tenant ID as the partition key to ensure data is evenly distributed
- Hot-spot avoidance: Each tenant has its own partition, avoiding hot-spot issues
- Predictable access: Tenant-based access patterns are more predictable
- Simplified queries: No need for complex parallel query logic
# Unified data model design
{
"tenant_id": "tenant1", # Partition key (HASH)
"entity_id": "uuid-123", # Sort key (RANGE)
"entity_type": "PRODUCT", # Entity type identifier
"created_at": "2024-01-01T00:00:00Z", # Creation time
"updated_at": "2024-01-01T00:00:00Z", # Update time
# ... business fields
}# Standard table structure template
TableName:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: tenant_id
AttributeType: S
- AttributeName: entity_id
AttributeType: S
KeySchema:
- AttributeName: tenant_id
KeyType: HASH
- AttributeName: entity_id
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5# Standard query pattern
response = table.query(
KeyConditionExpression=Key('tenant_id').eq(tenant_id),
ReturnConsumedCapacity='TOTAL'
)- Small data volumes (< 1000 entities/tenant): Simple queries are sufficient
- Large data volumes (> 1000 entities/tenant): Consider adding a GSI
- Cost-sensitive: The current design minimizes storage cost
- Back up existing data
- Run the migration script
- Validate the migration result
- Update the application code
- Delete the old data
- Query latency
- Throughput
- Error rate
- Cost
✅ Minimal design - The fewest fields and indexes
✅ Cost optimization - Reduced storage and write overhead
✅ Performance improvement - Simplified query logic
✅ Easy to maintain - Reduced code complexity
✅ Scalability - Room reserved for future growth
- Angular 20: Modern web application framework (standalone components, Material M3 theming)
- TypeScript 5.8: Type-safe JavaScript
- Angular Material: UI component library
- AWS Amplify v6 + @aws-amplify/ui-angular 5: Frontend integration with AWS services (authentication UI)
aws-serverless-saas-quickstart/
├── server/ # Backend services
│ ├── shared/ # Shared (control-plane) stack
│ │ ├── template.yaml # Shared resources CloudFormation/SAM template
│ │ ├── samconfig.toml # SAM config (stack: saas-control-stack)
│ │ ├── nested_templates/ # Nested CloudFormation templates
│ │ ├── custom_resources/ # Custom resources (e.g. usage-plan association)
│ │ ├── layers/ # Lambda layer dependencies
│ │ ├── auth/ # Authorizer and shared auth resources
│ │ └── tenant-management/ # Tenant registration / provisioning / user mgmt
│ ├── services/ # Tenant (application-plane) stack
│ │ ├── template.yaml # Tenant resources template (nested apps)
│ │ ├── samconfig.toml # SAM config (stack: stack-pooled)
│ │ ├── product-service/ # Product management service
│ │ ├── order-service/ # Order management service
│ │ └── tenant-api/ # Tenant API authorizer + throttling/monitoring
│ └── TenantPipeline/ # Tenant deployment pipeline (CDK)
├── client/ # Frontend applications
│ ├── Admin/ # System administrator interface
│ ├── Application/ # Tenant application interface
│ └── Landing/ # Landing / sign-up page
├── e2e/ # Playwright cross-platform smoke tests
├── scripts/ # Deployment and helper scripts
└── docs/ # Detailed documentation (see below)
This README is the high-level entry point. The in-depth architecture deep-dives live under docs/:
docs/ARCHITECTURE.md— overview pointer (technical stack, DB design, structure)docs/TENANT_MANAGEMENT.md— platform tenant management implementation (lifecycle, user/tenant association, RBAC, tiering)docs/API_CONFIGURATION.md— Admin and tenant API configuration-relationship deep-divesdocs/THROTTLING_AND_MONITORING.md— monitoring/operations, usage-plan throttling, and the CloudWatch throttling-metric mechanismdocs/CONFIGURATION.md|docs/LOCAL_TESTING.md|docs/CHANGES_FROM_WORKSHOP.md|docs/DEPENDENCY_AUDIT.md
Chinese versions of the deep-dives are under docs/zh-CN/.
- CRUD operations for products
- Supports multi-tenant data isolation
- Integrates monitoring and logging
- CRUD operations for orders
- Order-product association management
- Tenant-level data access control
- Tenant request authorization (Lambda authorizer)
- Per-tenant API throttling and CloudWatch monitoring
- Tenant registration and configuration
- Tenant activation/deactivation
- User management and permission control
- Tenant resource provisioning
- Admin (
client/Admin): System administrator console for managing tenants and users - Application (
client/Application): Tenant business application for managing products and orders - Landing (
client/Landing): Tenant registration and login page
- AWS CLI configured
- AWS SAM CLI installed
- Node.js 20.19+ or 22.12+ installed (required by Angular 20)
- Docker installed (used for SAM builds)
The backend is split into two stacks: the shared / control-plane stack (
server/shared) and the tenant / application-plane stack (server/services). Deploy the shared stack first.
cd server/shared
sam build -t template.yaml --use-container
sam deploy --config-file samconfig.tomlcd ../services
sam build -t template.yaml --use-container
sam deploy --config-file samconfig.tomlcd ../TenantPipeline
npm install
cdk bootstrap
cdk deploy --require-approval never# Admin application
cd client/Admin
npm install
npm run build
# Tenant application
cd ../Application
npm install
npm run build
# Landing page
cd ../Landing
npm install
npm run buildcd scripts
./deployment.sh
./geturl.sh- Applicable tiers: Basic, Standard, Premium
- Characteristics: Multiple tenants share the same infrastructure
- Isolation method: Data isolation achieved through application-layer logic
- Advantages: Cost-effective, suitable for small tenants
- User pool: Shared Cognito user pool
- Applicable tier: Platinum
- Characteristics: Each tenant has independent infrastructure
- Isolation method: Physical-level data isolation
- Advantages: Higher security, suitable for large enterprise tenants
- User pool: Independent Cognito user pool
- Infrastructure: A dedicated CloudFormation stack deployed automatically via CodePipeline
| Tier | Isolation Model | API Limit | User Pool | Infrastructure | Use Case |
|---|---|---|---|---|---|
| Basic | Pooled | Low | Shared | Shared | Small businesses |
| Standard | Pooled | Medium | Shared | Shared | Medium businesses |
| Premium | Pooled | High | Shared | Shared | Large businesses |
| Platinum | Silo | Highest | Independent | Dedicated | Enterprise customers |
- Identity authentication: AWS Cognito user pools
- API authorization: Lambda authorizer
- Data encryption: Encryption in transit and at rest
- Network security: VPC and security group configuration
- Access control: IAM roles and policies
# Start the local API
sam local start-api
# Start the frontend development server
cd client/Application
ng serveCross-platform test suite (Windows / macOS / Linux); see docs/LOCAL_TESTING.md for details:
# Backend: pytest + moto (in-memory mock DynamoDB, no Docker / AWS required)
pip install -r requirements-test.txt
pytest
# Frontend: Playwright runtime smoke test (first run ng build for each, then)
cd e2e && npm install && npx playwright install chromium && npx playwright testSee CI under .github/workflows/: backend-tests.yml (pytest on three platforms) and frontend-e2e.yml (builds the three apps + Playwright).
- Create a new service directory under
server/ - Implement the Lambda functions and the data access layer
- Update the CloudFormation templates
- Configure the API Gateway routes
- Modify the tenant table structure
- Update the tenant management service
- Adjust the frontend management interface
- Deployment failure: Check AWS permissions and quotas
- API call failure: Verify the API key and authorization configuration
- Frontend inaccessible: Check the CORS configuration and CloudFront distribution
- CloudWatch Logs
- X-Ray tracing
- API Gateway test console
Contributions are welcome! Please first read CONTRIBUTING.md and CODE_OF_CONDUCT.md.
Please report security issues privately following SECURITY.md. See CHANGELOG.md for version changes.
This project is open-sourced under the MIT-0 license. For upstream provenance and attribution, see NOTICE;
for differences from the upstream Workshop, see docs/CHANGES_FROM_WORKSHOP.md.
- AWS Serverless Application Model (SAM)
- AWS Lambda
- Amazon API Gateway
- Amazon DynamoDB
- AWS Cognito
- Angular Framework
If you have questions or suggestions, please submit feedback via GitHub Issues.