Skip to content

Project plan

This repo rebuilds the AWS Serverless SaaS Reference Solution from scratch, one small step at a time. Each step is one pull request with its own doc in docs/, and each step is deployed to AWS and verified before the PR is opened.

A multi-tenant SaaS app (products and orders) where many customer companies (“tenants”) share one deployment, and each tenant can only ever see its own data.

Architecture overview: web apps, control plane and application plane

Key ideas the reference solution teaches, and the step that introduces each one:

Idea Step
Control plane vs application plane 01, 08
Tiers (Basic / Standard / Premium = pooled, Platinum = silo) and API keys / usage plans per tier 02, 04, 09
Tenant identity: tenant id + role + tier as custom Cognito claims 03
Lambda authorizer that validates the JWT and vends tenant-scoped STS credentials 04
Data isolation in a shared (pooled) DynamoDB table using dynamodb:LeadingKeys 05
Tenant-aware logging, metrics and tracing hidden in a Lambda layer 04, 05
Tenant user management with role-based rules 07
Automated onboarding/offboarding driven by events 08
Silo deployment for premium customers 09
Admin and tenant web apps 10, 11
Rolling out code changes to every tenant stack 12
# Branch What it adds Deploys
01 step-01-control-plane CDK app scaffold + ControlPlaneStack built with the SaaS Builder Toolkit (SBT): system-admin Cognito pool, control plane API, EventBridge bus yes
02 step-02-bootstrap BootstrapStack: tenant→stack mapping table, one API key per tier stored in SSM yes
03 step-03-tenant-identity TenantTemplateStack (pooled): tenant Cognito user pool with tenantId / userRole / tenantTier attributes yes
04 step-04-api-authorizer Shared Python Lambda layer, tenant authorizer, REST API, usage plans per tier, /whoami debug endpoint, unit tests yes
05 step-05-product-service Product microservice (5 Lambdas + pooled table) with tenant isolation via scoped credentials yes
06 step-06-order-service Order microservice yes
07 step-07-user-management Tenant user management service (TenantAdmin / TenantUser rules) yes
08 step-08-onboarding SBT core application plane: provisioning + deprovisioning script jobs; onboard a pooled tenant end to end yes
09 step-09-silo-tier Platinum tier: a dedicated tenant stack per tenant yes
10 step-10-admin-app S3 + CloudFront hosting construct and the React admin app (system admin) yes
11 step-11-saas-app React SaaS app (tenant login, products, orders, users) yes
12 step-12-tenant-pipeline CodePipeline + Step Functions that updates every tenant stack in waves yes

Each step branches from main, is deployed and verified, then opened as a PR to main and merged with a merge commit. Each PR’s diff is exactly that step, so you can review it at any time, even after it’s merged.

Differences from the original (on purpose)

Section titled “Differences from the original (on purpose)”
  • React (Vite + TypeScript) instead of Angular for both web apps.
  • Latest versions: SBT 0.9.x (the original pins 0.3.9, whose API differs), Python 3.13 Lambdas on ARM64, Powertools for AWS Lambda v3, and PyJWT instead of python-jose.
  • A small /whoami endpoint in step 04 so the authorizer can be tested before any business service exists.
  • Lambda Insights and the commented-out canary deployment settings are left out.
  • AWS account with admin credentials configured (aws sts get-caller-identity works)
  • Node.js 20+, Python 3.12+, AWS CDK CLI (npx cdk)
  • Docker running (CDK uses it to bundle Python Lambdas)