Case Study

Launchpad

A multi-tenant platform design that turns AI-builder / vibe-coded apps into production ECS Fargate deployments, for owners who aren't engineers.

A capstone-scale system-design project from the same DevOps Institute cohort as Procal on EKS. Launchpad rents out its own AWS account: every user's app runs as an ECS Fargate service billed to Launchpad, not to the user, which is why the design leans so heavily on strict cost gating and a resource ledger that can never lose track of what actually exists in AWS. The focus here is the infrastructure layer: the control-plane/data-plane split, the provisioning engine, and the pipeline that turns an upload into a running service.

A pipeline with a cost gate

  1. 1

    Login & register

    GitHub OAuth. No password, no Cognito.

  2. 2

    Upload & scan

    The app's source (zip or GitHub repo) goes to S3, then deterministic marker-file detection (package.json, go.mod, and so on) identifies the runtime. Zero billable AWS resources so far.

  3. 3

    Config generated

    A Dockerfile and runtime config are generated from a per-runtime template, then optionally reviewed by an AI pass for framework-specific gaps the template doesn't know about. Still zero commitment.

  4. 4

    Paymentbillable

    A subscription is created and a payment method verified. This is the gate: nothing past this point runs without an active subscription, enforced in SQL with an EXISTS clause, not just app-layer code.

  5. 5

    Build imagebillable

    CodeBuild builds the image and pushes it to a per-application ECR repository.

  6. 6

    Infra provisioningbillable

    Step Functions calls the AWS SDK directly to create the task definition, target group, listener rule, and ECS service for this one application.

  7. 7

    Deploybillable

    The service comes up behind the shared ALB and becomes reachable.

  8. 8

    Live & dashboard

    CloudWatch-backed health and metrics, surfaced back to the app owner.

Stages 1–3 are ordinary API requests. Stages 4–7 are meant to run as one Step Functions execution, kicked off by a single endpoint: POST /applications/{id}/deployments, the only route that starts a job with a real AWS bill attached.

Control plane and data plane

Control plane — Launchpad itself

CloudFrontone distribution
S3SPA, /*
ALB/api/*
Go APIECS Fargate

Data plane — one tenant app

Shared ALBlistener rule per app
Target groupper app
ECS Fargate servicethe tenant's app

Frontend and API share one CloudFront distribution and origin, so the session cookie is HttpOnly + Secure + SameSite=Strict with no CORS at all. It carries a session id, never a self-contained JWT, so a session can be revoked instantly. Tenant apps deliberately share one ALB via per-app listener rules and target groups instead of provisioning an ALB per app.

Provisioning: AWS SDK, not Terraform

Launchpad's own baseline infrastructure, VPC, ECS clusters, IAM, RDS, is Terraform in the launchpad-infra repo. But a tenant's application infrastructure is created and torn down on demand, so it's provisioned by calling the AWS SDK for Go directly, not by running Terraform per app. The engine that replaces Terraform state for that path is a single table:

Write-ahead, always. A row in resources is inserted with status='creating' before the AWS API call, and its ARN is filled in only after that call succeeds. A crash mid-provisioning can never leave a resource that exists in AWS but isn't tracked, and quietly keeps billing.

Idempotent by constraint. Every insert uses UNIQUE (application_id, resource_type, logical_name) with an ON CONFLICT, the actual basis for retrying a Step Functions state, rather than a check-then-insert that races.

Teardown, strictly reversed. Resources are deleted from the highest dependency_order down to the lowest, never any other order; anything that fails to delete is marked orphaned instead of silently disappearing from the record.

Orchestration: Step Functions

Build → provision → deploy → release, along with their compensating (rollback) actions, are wrapped in one Step Functions state machine, so a failure partway through is corrected the same way a success is finished: by the state machine, not by a person. Each state maps to one AWS SDK call guarded by the write-ahead ledger above, so a retried state is safe to run twice.

Security and tenancy rules

  • Secret values never touch the database, an API response, or a log. Only the ARN is stored; ECS tasks read the secret at runtime through the task definition's secrets block.
  • Tenant scoping always comes from the session, never from a client-supplied parameter, for both database queries and CloudWatch queries.
  • A resource that belongs to a different tenant returns 404, not 403, so its existence is never leaked.
  • An uploaded app archive is untrusted input. Nothing inside it (a main.tf, a launchpad.yml, an unusual Dockerfile instruction) is ever read as infrastructure configuration.
  • AI output is never an infrastructure parameter. It's used only to classify an undetected runtime and to review a generated Dockerfile against the app's real manifest, never to choose CPU, memory, or health-check paths.
  • Every application image is referenced by digest, never by tag, since a tag can move and a production record shouldn't lose its meaning.

Tech stack

Application

Go
PostgreSQL
React

Control plane

ECS
ALB
CloudFront
AWS S3

Provisioning & orchestration

Step Functions
CodeBuild
ECR

Data & secrets

RDS
AWS Secrets Manager
KMS

Async & observability

SQS
CloudWatch

Infra baseline

Terraform

More Case Studies

Procal

A 4-service cost-estimate & approval platform, moved from ClickOps and manual SSH deploys to Terraform + Atlantis GitOps, with Jenkins-driven Ansible/Packer pipelines and per-service Grafana monitoring.

TerraformAtlantisJenkinsAnsibleGrafana
DevOps Institute
View case study →

Procal on EKS

Migrated Procal onto Kubernetes: from a hand-run kubeadm cluster to EKS driven entirely by GitOps (ArgoCD + Argo Rollouts), with zero static AWS credentials anywhere via Pod Identity.

EKSArgoCDArgo RolloutsHelmKaniko
DevOps Institute
View case study →

aform

An Airtable Forms clone built around a queue-decoupled write path (RabbitMQ + worker), with a hardened deployment flow: systemd, Nginx, UFW, S3-backed backups, and a real k6 load test.

GoRabbitMQAWSPrometheusNginx
DevOps Institute
View case study →

Ops Bot

A Claude-powered Telegram bot for incident triage, PR review, and infra ops, wired into Grafana, AWS, Bitbucket, SonarQube, and Jenkins via MCP.

Claude APIMCPPythonTelegramFastAPI
DevOps Institute
View case study →