AWS Capstone · Portfolio-grade8–12 hrs over a week

Ship a Production Web App to AWS

The project that convinces recruiters: a containerized app on ECS Fargate behind HTTPS, a private database, all in Terraform, deployed by a pipeline with no long-lived keys. The app is simple, the engineering is the point.

From your mentor

Most grad portfolios are click-built toys. This one says: I can design a network, run containers, manage secrets, automate delivery, and tear it all down for cost. That’s the actual job, and it’s rare on a junior résumé.

01

What you’re building (and why recruiters care)

One coherent system that exercises every domain in this track, network, compute, storage, identity, delivery, the way a real team runs it.

Time

8–12 hours, spread over a week

Cost

~$1–2/day while running, destroy after each session (you’ll learn how)

Difficulty

Capstone, ties the whole AWS track together

What you’ll build

A containerized web app on ECS Fargate behind an HTTPS load balancer, with PostgreSQL on RDS in private subnets, secrets in Secrets Manager, all defined in Terraform and deployed by GitHub Actions via OIDC.

User / browserRoute 53 + ACM (HTTPS)Application Load Balancer

VPC · 2 Availability Zones

Public subnets

ALBNAT gateway

Private subnets

ECS Fargate (app)RDS PostgreSQL
S3 (assets)Secrets Manager (DB creds)CloudWatch (logs · alarms)

Delivery (no long-lived keys)

GitHub Actions, OIDC assume-role →build → ECRdeploy → ECS

Nice, that’s the win

Keep the app itself tiny, a notes API, a URL shortener, anything. Recruiters won’t care what it does; they’ll care that it’s private-by-default, HTTPS, reproducible from code, and deployed without a single long-lived key. That combination is what separates “I followed a tutorial” from “I can do this job.”

The three things you walk away with

A live HTTPS URL on your own domain, a clean GitHub repo with an architecture diagram and README, and a working terraform destroy, proof you understand cost. Those three are your interview.
02

The architecture, decision by decision

Every choice here is a small piece of production judgment you can defend in an interview.

ComponentChoiceWhy this is the production answer
ComputeECS FargateRun containers without managing servers, the sweet spot between EC2 and full Kubernetes
Entry + TLSALB + ACM + Route 53HTTPS on a real domain; the load balancer is the only thing exposed
DatabaseRDS PostgreSQL (private subnets)Managed, backed-up, and unreachable from the internet
SecretsSecrets ManagerDB credentials never live in code, env files, or the task definition in plaintext
IdentityIAM task role + GitHub OIDCThe app and the pipeline get scoped, temporary credentials, no static keys
InfrastructureTerraformThe entire stack is reproducible and reviewable, one command stands it up or tears it down
DeliveryGitHub Actions → ECR → ECSPush to main builds the image and deploys it automatically
OperationsCloudWatch + BudgetLogs, a dashboard, an alarm, and a cost guardrail
03

The build, phase by phase

Build it in this order, each phase has a checkpoint so you always know it worked before moving on. Never skip a checkpoint.

  1. App in a container

    Get the app running locally in Docker, the cloud doesn’t care what language, only that it’s a container.

    ✓ Checkpoint:docker run serves the app on localhost.

  2. Network (as code)

    Terraform a VPC: public + private subnets across 2 AZs, IGW, and a NAT gateway.

    ✓ Checkpoint:terraform apply creates the VPC; subnets show in the console.

  3. Data tier (private)

    RDS PostgreSQL in the private subnets, credentials in Secrets Manager, an S3 bucket for assets.

    ✓ Checkpoint:RDS is “available” and NOT publicly accessible; the secret exists.

  4. Run the app

    Push the image to ECR; run it on ECS Fargate in private subnets behind the ALB.

    ✓ Checkpoint:The ALB DNS name returns your app over HTTP; target group is healthy.

  5. HTTPS + domain

    An ACM certificate, a Route 53 record, an HTTPS listener, and an 80→443 redirect.

    ✓ Checkpoint:https://yourapp.com loads with a valid padlock.

  6. The pipeline

    GitHub Actions builds, pushes to ECR, and updates ECS, authenticating via an OIDC role, no static keys.

    ✓ Checkpoint:A push to main auto-deploys; there are zero AWS keys in the repo.

  7. Production polish

    Autoscaling on the ECS service, a CloudWatch dashboard + alarm, and an AWS Budget.

    ✓ Checkpoint:The service scales out under load; an alarm and a budget are active.

Do it as code from phase 2 on

Resist the urge to click. From the VPC onward, write it in Terraform, even though it’s slower at first. That’s the whole signal you’re sending, and it makes the teardown one command.
04

The maturity moment: a pipeline with no keys

This is the part that makes a reviewer sit up, most juniors paste an AWS access key into GitHub secrets. You won't.

Instead of storing an AWS key, GitHub authenticates to AWS with OIDC: a trust relationship lets the workflow assume a scoped IAM role and receive short-lived credentials for that run only. Nothing long-lived ever leaves AWS.

aws cli
# register GitHub as an OIDC identity provider, the foundation of keyless CI
$ aws iam create-open-id-connect-provider --url https://token.actions.githubusercontent.com --client-id-list sts.amazonaws.com
AWS docs: create-open-id-connect-provider

Checkpoint, what you should see

A commit to main triggers the workflow, it assumes the role, builds and pushes the image to ECR, and ECS rolls out the new task, and a search of your repo for AKIA finds nothing.
?

Worth pondering

In the interview, say this out loud: “CI authenticates with GitHub’s OIDC provider and assumes a least-privilege role, so there are no long-lived AWS credentials anywhere.” It maps straight to the IAM lessons, and it’s exactly what a security-conscious team wants to hear.
05

The win

The moment it’s real.

🎉 You did it

You push a commit, watch the GitHub Action go green, refresh https://yourapp.com, and see your change live, served by a container that scaled itself, talking to a database the internet can’t reach, with a padlock in the address bar. You built and shipped a production system.
06

Cost discipline (this is a skill too)

Two resources actually bill: the NAT gateway and the load balancer (~$1–2/day). Treating teardown as routine is itself a thing to show off.

aws cli
# end every session with this, the whole stack disappears, the bill stops
$ terraform destroy
Terraform docs: destroy

The habit that signals seniority

Stand it up to demo or develop, then terraform destroy. Being able to rebuild from zero in minutes, and choosing to, to save money, is exactly the instinct teams want. Keep an AWS Budget alarm on as a backstop.
07

When it breaks (it will)

When it doesn’t work (it happens, work down this list)

ALB returns 503

The ECS task is unhealthy or not registered, check the target group health and the container’s health-check path and port.

App can’t reach the database

The RDS security group must allow the ECS task’s security group on 5432; both must be in the VPC’s private subnets.

Task can’t pull the image

Private subnets need a NAT gateway (or VPC endpoints for ECR/S3) for the pull, and the execution role needs ECR permissions.

HTTPS won’t validate

The ACM cert must be validated via a Route 53 record and be in the same region as the ALB.

Pipeline “not authorized to AssumeRole”

The role’s trust policy must reference your GitHub OIDC provider and restrict the repo/branch in the condition.

08

Make it recruiter-ready

The build is half the project. The presentation is the half recruiters actually see.

The README that gets callbacks

Open with a one-line what + the live URL. Add an architecture diagram. List the production traits as bullets (private DB, HTTPS, IaC, OIDC, autoscaling, monitoring). Show the two commands to stand it up and tear it down. End with “what I’d do next” (multi-region, blue/green, WAF), it shows you know where the ceiling is.

Interview talking points to rehearse

Why Fargate over EC2 or EKS · how the database stays private · how secrets reach the container · how CI authenticates without keys · how you’d make it highly available · what it costs and how you control it. You’ve touched every one of these by building it.

In plain English

One polished project like this beats ten half-finished ones. Put the repo at the top of your résumé and your LinkedIn, record a 2-minute demo video, and let the architecture diagram do the talking. You didn’t learn AWS, you operated it.

Next up

Starter scaffold (coming next)

A Terraform + GitHub Actions starter repo for this capstone is the next deliverable, so you start from a working skeleton and fill in each phase rather than from a blank file.