Skip to main content
The Address API is deployed on AWS using a combination of shared base infrastructure and service-specific resources. This document provides a comprehensive overview of the entire infrastructure stack.

Architecture diagram

                    Internet


              ┌────────────────┐
              │    Route53     │  address.in.{env}.commenda.io
              └───────┬────────┘


              ┌────────────────┐
              │  ALB (HTTPS)   │  Service-specific load balancer
              │  + ACM Cert    │  in PUBLIC subnets
              └───────┬────────┘

        ┌─────────────┼─────────────┐
        ▼             ▼             ▼
   ┌─────────┐   ┌─────────┐   ┌─────────┐
   │ECS Task │   │ECS Task │   │   ...   │  Fargate containers
   │(Fargate)│   │(Fargate)│   │         │  in PRIVATE subnets
   └────┬────┘   └────┬────┘   └─────────┘
        │             │
        └──────┬──────┘

        ┌────────────┐
        │  RDS       │  PostgreSQL in PRIVATE subnets
        │ (Postgres) │  Only accessible from ECS tasks
        └────────────┘

Infrastructure components

1. Networking (from base infrastructure)

ComponentDescriptionSource
VPCShared network foundationBase infrastructure
Public subnetsWhere the ALB lives (internet-accessible)Base infrastructure
Private subnetsWhere ECS tasks and RDS live (no direct internet access)Base infrastructure
VPC endpointsAllow private resources to reach AWS services (ECR, S3, CloudWatch)Base infrastructure

2. Load balancing (service-specific)

ComponentDescriptionCreated by
Application Load BalancerInternet-facing, handles HTTPS terminationThis service
ACM certificateSSL/TLS for address.in..commenda.ioThis service
Target groupRoutes to healthy ECS tasks, health checks on /healthzThis service
HTTP → HTTPS redirectAutomatic redirect from port 80 to 443This service

3. Compute (ECS Fargate)

ComponentDescriptionSource
ECS clusterShared cluster for all servicesBase infrastructure
ECS serviceManages task lifecycle (2 tasks by default for HA)This service
Task definitionDefines containers and their configurationThis service
Init containerRuns database migrations on startupThis service
App containerMain application (waits for init to succeed)This service
Task resources:
  • CPU: 256 units (0.25 vCPU)
  • Memory: 512 MB
  • Launch type: Fargate

4. Database (RDS PostgreSQL)

ComponentDescription
EnginePostgreSQL 15.12
Instance classdb.t4g.medium
Storage100 GB (auto-scales to 500 GB)
LocationPrivate subnets
AccessOnly from ECS tasks (security group restriction)
CredentialsAuto-generated, stored in Secrets Manager
Performance InsightsEnabled (7-day retention)
Backups35-day retention (production)
EncryptionEnabled at rest

5. Security

Security groups

Security groupPurposeIngress rules
ALB SGProtects load balancerHTTP (80) and HTTPS (443) from internet
ECS SGProtects ECS tasksTraffic only from ALB on container port
Postgres SGProtects RDS instancePostgreSQL (5432) only from ECS tasks

IAM roles

RolePurposePermissions
Execution roleECS task executionPull images from ECR, write logs to CloudWatch, read secrets from Secrets Manager
Task roleApplication runtimeSSM for ECS Exec debugging

6. Observability

CloudWatch logs

  • Log group: /ecs/{env}/address-api
  • Retention: 30 days
  • Streams:
    • ecs-init - Database migration logs
    • ecs - Application logs

CloudWatch alarms

AlarmThresholdDescription
CPU high> 80% for 10 minutesECS task CPU utilization
Memory high> 80% for 10 minutesECS task memory utilization
ALB 5xx errors> 10 in 5 minutesLoad balancer errors
Target 5xx errors> 10 in 5 minutesApplication errors
Unhealthy hosts> 0 for 2 minutesFailed health checks

7. Secrets management

All secrets are stored in AWS Secrets Manager:
SecretDescription
{env}-address-api-secretsContains RDS credentials and application secrets
Secrets included:
  • RDS_USERNAME - PostgreSQL username
  • RDS_PASSWORD - Auto-generated password
  • RDS_HOSTNAME - RDS endpoint
  • RDS_PORT - PostgreSQL port (5432)
  • RDS_DBNAME - Database name
  • GOOGLE_GEOCODING_API_KEY - Google API key (from CI)

Environment mapping

EnvironmentAWS accountDomainTerraform workspace
Staging127214192604address.in.staging.commenda.iostaging
Production429032495558address.in.commenda.ioprod

State management

All Terraform state is stored in S3 in the production account:
s3://tofu-backend-429032495558/
├── base.tfstate              ← Shared VPC, ECS cluster, etc.
└── env:/
    ├── staging/
    │   └── addresses-api.tfstate
    └── prod/
        └── addresses-api.tfstate
State locking: DynamoDB table tofu-backend prevents concurrent modifications.

Traffic flow

  1. User requests https://address.in.staging.commenda.io/api/v1/geoencode
  2. Route53 resolves to ALB DNS name
  3. ALB terminates SSL, forwards HTTP to target group
  4. Target group picks a healthy ECS task
  5. ECS task processes request, queries RDS if needed
  6. Response flows back through the same path

Deployment architecture

GitHub Release (v0.1.0)


  GitHub Actions

   ┌────┴────┐
   │         │
   ▼         ▼
Build     Terraform
Docker    Apply
   │         │
   ▼         │
Push to      │
  ECR ───────┤


     Update Task Definition


     ECS Rolling Deployment
     (0 downtime, circuit breaker)


     Smoke Test (/healthz)
Deployment strategy:
  • Rolling deployment: 100% minimum healthy, 200% maximum
  • Circuit breaker: Automatically rolls back on failure
  • Health check grace period: 60 seconds
  • Zero downtime: New tasks start before old tasks stop

Cost breakdown

Estimated monthly cost per environment:
ResourceCost/month
ALB$20-25
ECS Fargate (2 tasks)$20-30
RDS (db.t4g.medium, 100GB)$50-70
CloudWatch, Secrets Manager$5-10
Total$100-150
Note: Shared costs (VPC, VPC endpoints, ECS cluster) are paid by base infrastructure.

High availability

ComponentHA strategy
ALBMulti-AZ by default
ECS tasks2 tasks across multiple AZs
RDSSingle-AZ (staging), Multi-AZ (production)
SecretsReplicated across AZs automatically

Disaster recovery

ScenarioRecovery strategy
Task failureECS automatically replaces failed tasks
ALB failureAWS automatically replaces unhealthy ALB nodes
RDS failureAutomated backups (35-day retention), point-in-time recovery
Region failureManual deployment to another region (not automated)

Security features

  • Encryption at rest: RDS storage encrypted
  • Encryption in transit: HTTPS only (TLS 1.3)
  • Network isolation: ECS tasks and RDS in private subnets
  • Least privilege: IAM roles with minimal permissions
  • Secret rotation: Supported via Secrets Manager
  • Deletion protection: Enabled on RDS

Next steps