AWS Architecture

Pocket Family's AWS deployment on ECS Fargate and Aurora Serverless v2, using the AWS Free Tier.

AWS ECS FargateAurora Serverless v2TerraformAWS Lambda

Pocket Family’s demo instance gets low, irregular traffic, so the whole AWS deployment is built around services that scale to zero instead of provisioned capacity sitting idle. An Application Load Balancer routes to a single ECS Fargate task running the frontend (nginx) and backend (FastAPI) containers together, the backend talks to Aurora Serverless v2, and CSV imports run async through SQS and a Lambda instead of an always-on worker. Fargate, Aurora Serverless v2, and Lambda are all serverless for the same reason: nobody’s paying for compute between demo visits.

Deployment

AWS deployment diagram: ALB routes to a single Fargate task; Aurora, S3, SQS, and the import Lambda all sit outside the VPC, reached over a public IAM-authenticated relay due to Free Tier constraints.

  • ALB → Fargate. The load balancer’s target group only points at the frontend container, even though both frontend and backend run in the same task. Nginx proxies API calls to the backend over localhost:8000, they share a network namespace under awsvpc mode, so there’s no reason to expose the backend to the ALB directly.
  • One shared task, not two services. Frontend and backend run as containers in a single Fargate task instead of two separate services. That’s a free-tier decision, not an ideal one, it keeps the always-on footprint to one task instead of two.
  • Aurora Serverless v2, min_acu = 0. Scales to zero ACUs when idle (an AWS capability since March 2025), capped at 4 ACUs, the free-plan ceiling. A demo that sits untouched for days isn’t billed for a database doing nothing.
  • CSV import, async. The backend uploads the file to S3 and dispatches a job to SQS. An SQS-triggered Lambda does the actual import work and deletes the file from S3 when it’s done. No Celery worker runs on AWS at all, the Lambda scales to zero when the queue’s empty, which an always-on ECS worker never would.

Free Tier vs. Security

Aurora Serverless v2 on the AWS Free Tier requires a WithExpressConfiguration flag on cluster creation that neither Terraform nor CloudFormation exposes yet (confirmed as of May 2026). Express configuration also disables VPC networking on the cluster entirely, no subnet group, no security group. The backend and the import Lambda reach Aurora over a public IAM-authenticated relay endpoint instead, TLS-encrypted and authenticated with iam_database_authentication_enabled, not a database password.

That’s a real tradeoff, not a wash. Network isolation and IAM authentication are different security models, and losing the first one because a free-tier flag isn’t exposed in my tooling isn’t a decision I’d defend as ideal. What’s still true: there’s no password to leak, every connection is IAM-signed and TLS-encrypted, and the security groups that do exist (ALB → Fargate on port 80, Fargate-only ingress) are still least-privilege. The import Lambda stays off the VPC on purpose too: the default VPC has no NAT gateway, so a VPC-attached Lambda gets no public IP and no route to Aurora’s public endpoint at all, every connection just times out.

Why Serverless Over EC2 + RDS

EC2 and standard RDS are the more common default, and they’d have worked, but both bill for provisioned compute whether or not anyone’s using it. For a demo with sparse, unpredictable traffic, that’s paying for idle capacity most of the time. Fargate and Aurora Serverless v2 scale to the actual usage pattern instead of a guessed-at instance size, which is the whole point on a project with no real traffic to size against.

What I’d Run Without the Constraint

Ideal AWS deployment diagram: Aurora, both Fargate services, and the import Lambda sit in a private subnet behind real VPC security groups, with a NAT Gateway handling ECR and CloudWatch egress.

Without the free-tier restriction, Aurora would sit in a private subnet behind a real VPC security group, same as the Fargate tasks and the import Lambda, network isolation instead of an IAM relay. Frontend and backend would also run as two independent Fargate services instead of sharing a task, so either can scale or redeploy without touching the other.

That version isn’t free, though. Gateway Endpoints only cover S3 and DynamoDB, so ECR pulls and CloudWatch Logs still need a NAT Gateway (or their own paid Interface Endpoints), and a NAT Gateway bills per hour and per GB processed. The free-tier version’s security compromise gets traded for an actual AWS bill in the ideal one, there’s no version of this that’s both fully private and fully free.