Production-inspired serverless API project with API Gateway, AWS Lambda, AWS WAF, API keys, CloudWatch, SNS, EventBridge, and Terraform
A production-inspired AWS serverless API project that demonstrates secure API exposure, Lambda-backed routing, API key enforcement, WAF protection, access logging, monitoring, and advanced alerting.
This project deploys a secure serverless REST API platform on AWS using Terraform.
The API exposes two Lambda-backed routes:
/py— served by a Python Lambda function/js— served by a JavaScript/Node.js Lambda function
Both routes return styled dynamic HTML pages and are protected with API Gateway controls, AWS WAF managed rule sets, API key enforcement, usage plan throttling, and CloudWatch-based observability.
The project also includes an advanced alerting workflow where CloudWatch alarm state changes are routed through EventBridge into a Lambda formatter, which sends actionable troubleshooting messages through SNS.
This project is intentionally small, but it demonstrates practical production-style API engineering patterns:
- REST API design with API Gateway
- serverless compute with AWS Lambda
- Infrastructure as Code with Terraform
- API key-based client access control
- usage plans, throttling, and quotas
- WAF managed rule protection
- CloudWatch access logging and alarms
- SNS-based notifications
- EventBridge-driven alert processing
- custom Lambda-based alert formatting
Public APIs need more than a working endpoint.
A real API should be protected, observable, controlled, and supportable. Many beginner serverless projects stop at:
- one Lambda function
- one public endpoint
- no WAF protection
- no API key controls
- no usage plan
- no access logs
- no alarms
- no alerting workflow
- no operational troubleshooting path
That creates problems in production-style environments:
- anyone can call the API without control
- abusive traffic can overload the backend
- attacks may reach the application layer unchecked
- failures are hard to troubleshoot
- logs are not structured around request visibility
- alarms do not provide actionable guidance
This project addresses those gaps by building a small but realistic secure API platform.
Build a Terraform-managed AWS serverless API that demonstrates how to expose Lambda functions through API Gateway while applying practical production controls:
- secure the API entry point with AWS WAF
- require API key access through API Gateway
- control traffic with usage plans and throttling
- log API requests for troubleshooting
- monitor errors and latency with CloudWatch alarms
- send alert notifications through SNS
- use EventBridge and Lambda to generate actionable alert messages
Save your architecture image as:
Evidence/01-architecture/architecture-diagram.png
Client / Browser / curl
↓
API Gateway REST API
↓
AWS WAF evaluates the request
↓
API Gateway checks for x-api-key header
↓
Usage plan applies throttling and quota controls
↓
API Gateway routes request to /py or /js
↓
Python Lambda or JavaScript Lambda executes
↓
Lambda returns styled HTML response
↓
API Gateway sends response back to client
↓
API Gateway, Lambda, and WAF logs go to CloudWatch
↓
CloudWatch alarms monitor errors and latency
↓
EventBridge captures alarm state changes
↓
Advanced alerting Lambda formats the incident message
↓
SNS sends the alert email
| Category | Technologies |
|---|---|
| Cloud Provider | AWS |
| Infrastructure as Code | Terraform |
| API Layer | Amazon API Gateway REST API |
| Compute | AWS Lambda |
| Runtime 1 | Python 3.12 |
| Runtime 2 | Node.js / JavaScript |
| Security | AWS WAF, API keys, IAM roles |
| Traffic Control | API Gateway usage plans, throttling, quotas |
| Logging | CloudWatch Logs, API Gateway access logs, WAF logs |
| Monitoring | CloudWatch alarms |
| Notifications | Amazon SNS |
| Event Routing | Amazon EventBridge |
| Alert Automation | Advanced alerting Lambda |
| API Gateway exposes controlled REST endpoints backed by Lambda functions. | Python and JavaScript Lambda functions serve dynamic API responses. | AWS managed rule groups help protect the API from common web threats. |
API clients must send an API key through the x-api-key header.
|
| API Gateway usage plans control throttling and monthly request quotas. | API Gateway access logs capture request ID, status code, latency, IP, and route. | CloudWatch alarms detect API 5XX errors, high latency, and Lambda failures. | EventBridge and Lambda create actionable SNS alert messages with suggested fixes. |
- A Regional API Gateway REST API
- A
/pyroute backed by a Python Lambda function - A
/jsroute backed by a JavaScript Lambda function - Lambda proxy integrations for full request/response handling
- API Gateway deployment and
prodstage - API key requirement for protected API access
- Usage plan with throttling and monthly quota
- AWS WAF web ACL attached to the API Gateway stage
- AWS managed WAF rule groups for common attacks, known bad inputs, and SQL injection
- WAF rate-based rule for basic abuse protection
- API Gateway access logs in CloudWatch
- Lambda execution logs in CloudWatch
- WAF logs in CloudWatch
- CloudWatch alarms for API and Lambda issues
- SNS topic and email subscription for notifications
- EventBridge rule for CloudWatch alarm state changes
- Advanced alerting Lambda that formats actionable alert emails
| AWS Resource | Purpose |
|---|---|
| Amazon API Gateway | Public REST API entry point for /py and /js routes. |
| AWS Lambda | Runs the Python, JavaScript, and advanced alerting functions. |
| AWS WAF | Protects the API Gateway stage using managed rules and rate limiting. |
| API Gateway Usage Plan | Applies client-level throttling and monthly request quotas. |
| API Gateway API Key | Requires clients to send an x-api-key header before accessing protected routes. |
| CloudWatch Logs | Stores Lambda logs, API Gateway access logs, and WAF logs. |
| CloudWatch Alarms | Detects API 5XX errors, high latency, and Lambda function failures. |
| Amazon SNS | Sends email notifications for production-style alerts. |
| Amazon EventBridge | Routes CloudWatch alarm state changes to the advanced alerting Lambda. |
| IAM Roles and Policies | Provides least-privilege permissions for Lambda, API Gateway logging, and SNS publishing. |
| Terraform | Provisions and manages the full infrastructure stack. |
Enterprise-Serverless-API-Security-Platform-on-AWS/
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars.example
├── advanced-alerting.py
├── lambda-js/
│ └── index.js.tpl
├── lambda-py/
│ └── index.py.tpl
├── Evidence/
│ └── 01-architecture/
│ └── architecture-diagram.png
└── docs/
├── architecture.md
└── security-controls.md
| Route | Method | Access | Description |
|---|---|---|---|
/py |
ANY |
API key required | Runs the Python Lambda and returns a styled dynamic HTML page. |
/js |
ANY |
API key required | Runs the JavaScript Lambda and returns a styled dynamic HTML page. |
/prod/py → Python Function page
/prod/js → Java Function page
Both routes require the API key to be sent through the request header:
x-api-key: YOUR_API_KEYgit clone <your-repository-url>
cd Enterprise-Serverless-API-Security-Platform-on-AWSCreate a terraform.tfvars file:
alert_email = "your-email@example.com"terraform initterraform validateterraform planterraform apply -auto-approveAfter deployment, AWS SNS sends a confirmation email.
Click Confirm subscription before expecting alert emails.
terraform output -raw api_key_valueAPI_KEY=$(terraform output -raw api_key_value)
curl -H "x-api-key: $API_KEY" \
"https://<api-id>.execute-api.us-east-1.amazonaws.com/prod/py?name=Gavin"API_KEY=$(terraform output -raw api_key_value)
curl -H "x-api-key: $API_KEY" \
"https://<api-id>.execute-api.us-east-1.amazonaws.com/prod/js?name=Gavin"aws cloudwatch set-alarm-state \
--alarm-name "<project-name>-api-5xx-errors" \
--state-value ALARM \
--state-reason "Testing advanced formatted API Gateway 5XX alert"Expected result:
- CloudWatch alarm enters
ALARMstate. - EventBridge captures the state change.
- Advanced alerting Lambda runs.
- Lambda formats the message with likely cause and suggested fixes.
- SNS sends an email notification.
Reset test alarm:
aws cloudwatch set-alarm-state \
--alarm-name "<project-name>-api-5xx-errors" \
--state-value OK \
--state-reason "Testing complete"The API Gateway stage is protected by an AWS WAF web ACL using managed rule groups:
- AWS Managed Common Rule Set
- AWS Managed Known Bad Inputs Rule Set
- AWS Managed SQL Injection Rule Set
- Rate-based rule by source IP
The /py and /js routes require an API key through the x-api-key header.
This models controlled client access for partner, internal, or application consumers.
The usage plan applies:
- request rate limits
- burst limits
- monthly quota controls
This prevents uncontrolled client usage and helps protect the backend Lambda functions.
IAM roles are scoped by service responsibility:
- Lambda execution role writes function logs
- API Gateway role pushes logs to CloudWatch
- advanced alerting Lambda publishes to SNS
- API Gateway receives permission to invoke Lambda
This project includes multiple layers of visibility:
| Layer | What It Captures |
|---|---|
| API Gateway Access Logs | request ID, source IP, route, method, status code, latency, user agent, API key ID |
| Lambda Logs | function execution details, incoming events, application logs, runtime errors |
| WAF Logs | inspected requests, matched rules, blocked traffic, rate-based activity |
| CloudWatch Alarms | API 5XX errors, high latency, Lambda errors |
| SNS Alerts | email notifications for operational events |
| Advanced Alerting Lambda | formatted alarm messages with possible causes and suggested fixes |
Instead of relying only on raw CloudWatch alarm emails, this project uses an advanced alerting path:
CloudWatch Alarm
↓
EventBridge Alarm State Change Rule
↓
Advanced Alerting Lambda
↓
SNS Topic
↓
Email Notification
The advanced-alerting.py function reads the alarm event and dynamically generates:
- alarm name
- state transition
- AWS region
- account ID
- metric namespace and metric name
- alarm reason
- likely cause
- suggested troubleshooting steps
- recommended investigation workflow
This makes alerts more actionable and closer to what an operations team would expect in a production environment.
| Problem | Why It Mattered | Architectural Decision | Implementation |
|---|---|---|---|
| Exposing Lambda functions through HTTP | Lambda functions need an HTTP entry point for users and API clients. | Use API Gateway REST API with Lambda proxy integration. | Created /py and /js API Gateway resources, methods, and integrations. |
| Supporting two runtimes | The project needed to show more than one Lambda runtime. | Use separate Python and JavaScript Lambda functions. | Deployed independent Lambda functions with separate handlers and packaging. |
| Lambda packaging errors | Lambda requires the handler file to exist at the root of the zip package. | Package files as index.py and index.js inside deployment zips. |
Used Terraform archive packaging and corrected handler mappings. |
| Securing public API access | A public API should not be exposed without protection. | Add WAF, API key enforcement, and usage plan throttling. | Attached WAF to the API stage and required x-api-key for route access. |
| Preventing abusive traffic | APIs need protection against request spikes and repeated calls. | Use WAF rate limiting and API Gateway throttling. | Added WAF rate-based rule and API Gateway method settings. |
| Making the API observable | Production APIs need request visibility for troubleshooting. | Enable API Gateway access logs and Lambda logs. | Sent structured access logs and function logs to CloudWatch. |
| Detecting operational failures | Logs are useful, but production systems need alarms. | Add CloudWatch alarms for API and Lambda failure modes. | Created alarms for 5XX errors, high latency, and Lambda errors. |
| Making alerts actionable | Default alarm notifications often lack troubleshooting context. | Route alarm events through EventBridge into a formatter Lambda. | Built advanced-alerting.py to generate SNS messages with likely causes and suggested fixes. |
| Keeping infrastructure reproducible | Manual cloud configuration is hard to repeat and review. | Manage the full stack through Terraform. | Defined API Gateway, Lambda, WAF, CloudWatch, SNS, EventBridge, IAM, and usage plans as code. |
This project is production-inspired but intentionally scoped to stay understandable and demo-ready.
Future improvements could include:
- Add Cognito User Pool authorizer
- Add Lambda authorizer for custom token validation
- Separate public, partner, and admin routes
- Replace API keys with identity-aware authorization for user-level access
- Add GitHub Actions or GitLab CI/CD
- Add Terraform plan/apply workflow with manual approval
- Add Checkov or tfsec scanning
- Add canary deployments for safer API releases
- Add OpenAPI specification
- Add
/healthand/statusroutes - Add structured JSON error responses
- Add developer-facing API documentation
- Add CloudWatch dashboard
- Add DynamoDB audit table for structured request metadata
- Add custom domain with ACM TLS certificate
- Add Route 53 DNS mapping
- Add multi-environment Terraform structure for dev, stage, and prod
This project intentionally does not include:
Cognito authentication
custom domain
CI/CD pipeline
OpenAPI specification
DynamoDB audit table
CloudWatch dashboard
multi-region failover
canary deployments
full admin portal
These are known future improvements. The current version focuses on building and securing the API foundation first.
Important
This project demonstrates practical cloud engineering by turning a simple Lambda API into a secured, observable, and production-inspired serverless API platform.
Instead of stopping at a basic public Lambda endpoint, this project adds the controls that matter in real environments:
| AWS WAF inspects requests before they reach the backend Lambda functions. | API keys and usage plans control who can call the API and how often. | CloudWatch logs and alarms make the API easier to troubleshoot and monitor. |
| EventBridge and Lambda turn alarm events into useful troubleshooting messages. | Terraform provisions the full AWS stack consistently as code. | Lambda and API Gateway provide a lightweight, scalable API backend. |
Request API
↓
WAF Inspection
↓
API Key Validation
↓
Usage Plan Throttling
↓
Lambda Execution
↓
CloudWatch Logging
↓
Alarm Detection
↓
EventBridge Routing
↓
SNS Alert Notification
| Area | Value Shown |
|---|---|
| API Engineering | REST API routes backed by serverless compute |
| Cloud Security | WAF, API keys, IAM roles, and controlled access |
| Infrastructure as Code | Full AWS deployment managed through Terraform |
| Observability | Access logs, Lambda logs, WAF logs, and alarms |
| Operations | SNS notifications and actionable alert formatting |
| Interview Readiness | Clear explanation of request flow, security layers, and monitoring design |
I build hands-on cloud projects designed to reflect practical engineering work rather than simple demos. My focus is on AWS infrastructure, Infrastructure as Code, automation, security-minded design, and real implementation patterns that translate into production environments.
