This project deploys a serverless URL shortener on AWS using Terraform.
- Creates short URLs with
POST /newurl - Redirects users with
GET /{shortid} - Stores mappings in DynamoDB
- Uses API Gateway and Lambda for fully managed compute and routing
- Uses Route 53 + ACM for a custom API domain
- Applies a WAF ACL to API Gateway
Core AWS services used:
- API Gateway (Regional)
- Lambda (create URL, retrieve URL)
- DynamoDB (
short_idas partition key,PAY_PER_REQUESTbilling) - IAM role/policy for least-privilege Lambda access to DynamoDB
- Route 53 + ACM + API Gateway custom domain
- WAFv2 (IP allowlist pattern)
apigateway.tf: API resources, methods, integrations, deployment, stagelambda.tf: Lambda modules, runtime config, IAM role and policy modulesdynamodb.tf: DynamoDB table definitiondomain.tf: ACM, API custom domain, base path mapping, Route 53 recorddata.tf: AWS account/region/Route53 lookups and IAM policy documentwaf.tf: Web ACL, logging, and API stage associationbackend.tf: Terraform S3 backend configprovider.tf: AWS provider regionurl-create-lambda/lambda_function.py: Create short URL handlerurl-retrieve-lambda/lambda_function.py: Retrieve/redirect handler
- Terraform installed
- AWS credentials configured
- Route 53 hosted zone for your domain
- S3 bucket for Terraform remote state (or adjust backend strategy)
This repo currently contains environment-specific values. Update these to your own environment:
provider.tf- AWS region
backend.tf- S3 backend bucket/key/region
data.tfdata "aws_route53_zone" "zone"domain name
domain.tf- ACM and API custom domain values
lambda.tfAPP_URLenvironment variable used when generating short URLs
From the project root, run:
terraform init
terraform plan
terraform apply- Method:
POST - Path:
/newurl - Request body:
{
"long_url": "https://www.google.com/search?q=test"
}- Success response:
- Status:
200 - Body: short URL string
- Status:
- Method:
GET - Path:
/{shortid} - Success response:
- Status:
302 - Redirect location returned from integration mapping
- Status:
- Lambda scales with concurrent requests (subject to account quotas)
- API Gateway scales automatically
- DynamoDB on-demand mode is suitable for variable traffic patterns
- Managed AWS services reduce operational overhead and single-host risk
- Lambda execution role has scoped DynamoDB permissions
- API methods currently use
authorization = "NONE" - WAF configuration currently defaults to block and allows only an IP set
- In the current
waf.tf, the IP set is derived from your current public IP at apply time - If your IP changes, requests may be blocked until the ACL is updated/re-applied
- In the current
- Call
POST /newurlwith a validlong_url - Confirm a new item exists in DynamoDB
- Call
GET /{shortid} - Confirm redirect works and
hitsincrements
To remove all resources:
terraform destroy