Skip to content
LEAPDocs

Deployment architecture

Three services, one load balancer, and a managed data layer — all defined in Terraform.

The services

webThe static React bundle. No server-side rendering, no application state.
apiThe Express application — every domain router, validated and institution-scoped.
workerBackground jobs: extraction, authoring, materials, grading, concept tagging.

Why the worker is separate

Generating a course takes minutes. If that ran in the API, a burst of course creation would starve interactive requests — the dashboard would hang because someone else uploaded a syllabus. Separate services mean the two scale independently.

Data layer

Aurora PostgreSQLThe system of record. Serverless, with a warm floor so the first request of the morning does not pay a cold start.
RedisJob queue and short-lived coordination state.
S3Syllabi, scanned scripts, recordings, generated decks and audio. Served through the application, never as a public bucket.
CognitoIdentity. The application holds a bearer token rather than a host-locked cookie.

Infrastructure as code

Everything is Terraform, split into modules — network, database, compute, storage, cognito, secrets, waf, observability, security and dns. A change to certificate policy is reviewable independently of a change to task sizing.

  • Containers run on ECS Fargate behind an Application Load Balancer with per-service autoscaling.
  • A WAF sits in front with global rate rules; ALB access logs are retained.
  • GuardDuty and CloudTrail are enabled with alarms routed to a notification topic.
  • A wildcard certificate covers tenant subdomains, so adding an institution needs no certificate change.

Cost shape

The database is the largest infrastructure line by a wide margin, which makes its minimum capacity the highest-leverage cost setting. Right-sizing tasks and removing unused components — an idle read replica, an unused connection proxy — were the other meaningful reductions.