A serverless image management platform on AWS — 7 Python Lambdas behind a JWT-protected API Gateway, Rekognition auto-tagging, reverse image search, and 33 resources managed entirely in Terraform.
Problem
The brief was simple: build an image storage platform that scales without managing servers. The stretch goal I added — making images findable by what's actually in them, including searching by a query image rather than a keyword — turned out to be the most interesting engineering problem on the project.
My Contribution
I designed and built the full AWS architecture, the Python backend, the Next.js dashboard and the infrastructure pipeline:
- Built a serverless image platform on AWS using 7 Python Lambda functions behind a JWT-protected API Gateway, covering upload, gallery listing, tag search, reverse image search, tag editing, deletion and object detection. The Next.js dashboard is served through CloudFront from an S3 static export
- Wrote all infrastructure as code in 5 reusable Terraform modules for compute, API, auth, storage and observability, managing 33 AWS resources across 3 GitHub Actions workflows that authenticate with OIDC so no long-lived credentials are stored
- Added Rekognition label detection triggered by S3 upload events, then built reverse image search by matching query-image labels against a DynamoDB global secondary index
- Isolated user data using Cognito JWT auth with 4-hour token expiry, API Gateway authorizers, ownership checks returning 403 on mismatch, and 1-hour presigned S3 URLs
- Covered the codebase with 59 pytest and moto unit tests and ran local development against LocalStack, with 4 CloudWatch alarms wired to SNS email alerts, an SQS dead-letter queue and X-Ray tracing
Architecture
Seven Python Lambdas sit behind API Gateway, one per operation: upload, gallery listing, tag search, reverse image search, tag editing, deletion and object detection. Images land in S3 and are served back through 1-hour presigned URLs. Landing an object in the bucket fires an S3 event that triggers the detection Lambda, which calls Rekognition for labels and writes them to DynamoDB alongside the image metadata — so tagging happens out of band rather than blocking the upload response.
Reverse image search reuses the same detection path: run Rekognition over the query image, then match its labels against a DynamoDB global secondary index built on the label attribute. That avoids standing up a separate vector store for what is fundamentally a label-intersection problem.
Auth runs through Cognito with 4-hour token expiry, enforced at API Gateway with a JWT authorizer, and every handler re-checks ownership and returns 403 on a mismatch — the gateway proves who you are, the handler proves the object is yours. Presigned URLs expire after an hour so a leaked link stops working.
Everything is Terraform: 5 modules split by concern (compute, API, auth, storage, observability), applied through 3 GitHub Actions workflows that assume a role via OIDC, so there are no long-lived AWS keys in the repo or in CI secrets. Failures land in an SQS dead-letter queue, 4 CloudWatch alarms publish to an SNS topic for email alerts, and X-Ray traces the request path across services.
Outcomes
A working serverless platform where images are auto-tagged on upload and retrievable by tag or by example image, with zero servers to manage and the whole environment reproducible from terraform apply. The test suite runs 59 pytest cases against moto, and local development runs against LocalStack, so the AWS-shaped parts of the code are testable without touching a real account.
Learnings
Infrastructure as code changes what "done" means. Once the whole environment is 33 Terraform-managed resources behind OIDC-authenticated workflows, rebuilding from scratch is a non-event — and that safety net is what made it reasonable to keep restructuring the architecture. The other lesson was observability: dead-letter queues, alarms and tracing are much cheaper to add while building than to retrofit after something silently fails in an async path.