A serverless Event Registration & Ticketing System, built entirely on AWS.
π Live Demo: https://d24m8nf71z49d9.cloudfront.net
- Overview
- The Problem
- The Solution
- Architecture
- Tech Stack
- Features
- Screenshots
- Project Structure
- Getting Started
- Testing
- CI/CD Pipeline
- Monitoring & Security
- Cost Optimization
- Lessons Learned
- Future Improvements
- Documentation
- Author
TicketMe replaces manual, spreadsheet-based event registration workflows with a fully serverless, cloud-native REST API and web application. It handles event discovery, registration, duplicate/capacity prevention, cancellation, email confirmations and real-time monitoring, all without managing a single server.
Organizations commonly manage event signups through Microsoft Forms feeding into Excel spreadsheets. This approach:
- Doesn't scale past a handful of events or attendees
- Has no real-time capacity enforcement, overbooking is common
- Allows duplicate registrations with no automated prevention
- Provides no automated confirmations or notifications
- Offers zero operational visibility (no logs, no alerts, no monitoring)
A serverless system where:
- Events and registrations live in DynamoDB, not spreadsheets
- Business logic runs in AWS Lambda, scaling automatically with demand and costing nothing when idle
- API Gateway exposes a clean REST API consumed by a modern frontend
- SNS sends automated registration confirmations
- CloudWatch monitors error rates in real time and alerts via SNS if they exceed 5%
- AWS Budgets guards against unexpected cost
- The entire system is defined as code (Terraform) and deployed via a tested, automated CI/CD pipeline (GitHub Actions)
See docs/architecture/ for the full architecture writeup and data model.
| Layer | Technology |
|---|---|
| Cloud Provider | AWS |
| Compute | AWS Lambda (Python 3.12) |
| API | Amazon API Gateway (REST) |
| Database | Amazon DynamoDB |
| Notifications | Amazon SNS |
| Monitoring | Amazon CloudWatch (Logs, Metric Alarms) |
| Cost Control | AWS Budgets |
| Infrastructure as Code | Terraform |
| CI/CD | GitHub Actions |
| Frontend | Vanilla JavaScript (ES Modules), CSS3, HTML5 |
| Hosting | Amazon S3 + CloudFront (CDN, HTTPS) |
| Testing | pytest, moto (AWS mocking) |
- Browse, search, and filter live events
- Register for events with real-time validation
- Duplicate registration prevention (per email + event)
- Capacity enforcement using atomic, race-condition-safe DynamoDB updates
- View and cancel registrations by email
- Skeleton loading states, toast notifications, empty/error states
- Dark/light theme toggle
- Least-privilege IAM, a dedicated role per Lambda function
- CloudWatch error-rate alarms (metric math: errors Γ· invocations)
- AWS Budgets cost-tracking safety net
- Fully automated CI: unit tests + Terraform validation on every push/PR
| Events | Registration | My Registrations |
|---|---|---|
![]() |
![]() |
![]() |
| DynamoDB | Lambda | API Gateway |
|---|---|---|
![]() |
![]() |
![]() |
| CloudWatch Alarms | SNS Topics | AWS Budget |
|---|---|---|
![]() |
![]() |
![]() |
| GitHub Actions CI | Test Results |
|---|---|
![]() |
![]() |
ticketme/ βββ backend/ β βββ lambda/ β βββ list_events_handler/ β βββ register_handler/ β βββ get_registrations_handler/ β βββ cancel_registration_handler/ β βββ shared/ # response_utils, logger, validators βββ frontend/ β βββ index.html β βββ css/ # design system, components, animations β βββ js/ β βββ api.js # centralized API client β βββ router.js # hash-based SPA router β βββ state.js β βββ views/ # events, registrations β βββ components/ # eventCard, modal, toast βββ infrastructure/ # Terraform: DynamoDB, IAM, Lambda, β # API Gateway, S3, CloudFront, SNS, β # CloudWatch alarms, AWS Budgets βββ tests/ # pytest + moto unit tests βββ scripts/ # build & deploy automation βββ docs/ β βββ architecture/ β βββ api/ β βββ screenshots/ β βββ deployment-guide.md βββ presentation/ βββ .github/workflows/ # CI: backend tests, Terraform validate
Full step-by-step setup instructions are in docs/deployment-guide.md. Summary:
# Clone
git clone https://github.com/Fiber-dunstan/TICKETME.git
cd TICKETME
# Backend: set up Python environment
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install -r backend/requirements.txt
# Run tests
pytest tests/ -v
# Deploy infrastructure
cd infrastructure
terraform init
terraform apply
# Seed sample data
cd ..
python scripts/seed_events.py
# Deploy frontend
.\scripts\deploy_frontend.ps114 unit tests cover all 4 Lambda functions, happy paths and every failure branch (validation errors, missing resources, duplicates, capacity limits) using moto to simulate AWS services in-memory, with zero cost and no real AWS calls.
pytest tests/ -vTwo GitHub Actions workflows run automatically:
backend-tests.ymlruns the full pytest suite on every push/PR tomain/developterraform-validate.ymlchecks Terraform formatting and validity on every change toinfrastructure/
Branch protection on main requires both checks to pass before a merge is allowed, a genuine automated quality gate, not just advisory.
Branching strategy: main (stable) β develop (integration) β feature/* branches, via Pull Requests.
- Least-privilege IAM: each Lambda has its own role with only the exact permissions it needs
- Input validation & sanitization on every write endpoint
- CloudWatch Logs for every function, with 14-day retention (cost control)
- CloudWatch Alarms: error rate (errors Γ· invocations) monitored per function, alerting via SNS if it exceeds 5%
- AWS Budgets: monthly spend alerts at 80% actual / 100% forecasted
- DynamoDB
PAY_PER_REQUESTbilling no idle cost - Lambda pay only per invocation, generous AWS Free Tier
- CloudWatch Log Groups with explicit 14-day retention (prevents unbounded log storage cost)
- CloudFront
PriceClass_100cheapest tier, sufficient edge coverage - AWS Budgets as an explicit safety net
A few real debugging challenges worth highlighting (detailed in docs/troubleshooting.md):
- Python module-name collisions across Lambda handlers during testing
- DynamoDB reserved keywords (
capacity,status) requiringExpressionAttributeNames - API Gateway CORS preflight requiring explicit
passthrough_behavior - API Gateway not reliably URL-decoding path parameters, solved with explicit
unquote() - Git branching discipline the practical cost of merging into the wrong base branch, and how consistent
git statuschecks andgh pr create --base developsolved it for good
- Single-table DynamoDB design for reduced read/write costs at scale
- Cognito-based authentication for an admin dashboard
- QR code ticket generation and PDF ticket download
- Event-attendance forecasting using historical registration data (ML-ready architecture)
- Custom domain + ACM certificate for the CloudFront distribution
- Terraform remote state (S3 backend + DynamoDB locking) for team collaboration
- Per-user registration confirmation emails via Amazon SES (SNS's static-subscriber model only supports notifying a fixed operator address, not dynamic per-registrant recipients)
Dunstan Banyaa Built as a capstone project for the Azubi Africa AWS Cloud & AI Intensive Program.
None Selected











