← Back to Documentation
Infrastructure Review

Native Backend — Infrastructure (ECS)

A read-only review of the ECS cluster that runs the native backend API — its services, task definition, logging, event capture and auto-scaling posture — fronted by an ALB, images from ECR, connected to the Aurora PostgreSQL database documented in Native Backend — Database.

Compute
ECS · Fargate
Region
us-east-1
Services
2 · 2 running
Review date
2026-07-22
Table of Contents
01

Overview

The native backend API runs as containers on Amazon ECS using the Fargate launch type (serverless containers — no EC2 instances to manage) in us-east-1, the same region as its Aurora PostgreSQL database. It is deployed and managed by AWS CDK (the image repository and task definitions carry CDK asset naming), consistent with a "built by Codex" native stack that is separate from the legacy Portal CI/CD.

Traffic flows from the internet through an internet-facing Application Load Balancer to the ECS service tasks (container api on port 8080), which talk to Aurora over the private network. Container images are pulled from a private ECR repository. Application logs stream to CloudWatch Logs, and Container Insights is enabled on the cluster for metrics/observability. See the companion database documentation for the schema and DB access model.

1
ECS Cluster
2
Services (Fargate)
2
Running Tasks
0
Pending Tasks
02

Architecture Diagram

🌐
Internet
clients
⚖️
ALB
revique-api-dev-alb
rev****.elb.amazonaws.com
📦
ECS Service
Fargate tasks
container api :8080
🗄️
Aurora PostgreSQL
rev****.rds.amazonaws.com
db: revique
📜
CloudWatch Logs
/revique/revique-api/dev/api · 30-day retention
📊
Container Insights
ENABLED on cluster
🐳
ECR
private image repo (CDK asset)
🔔
EventBridge
no ECS rules found
Reading the diagram: the ALB is the only public entry point; ECS tasks run with assignPublicIp = DISABLED on private subnets and reach Aurora over the VPC. Logs and metrics fan out to CloudWatch on the side.
03

ECS Cluster

PropertyValue
Cluster namerevique-api-dev-cluster
ARNarn:aws:ecs:us-east-1:292****:cluster/revique-api-dev-cluster
StatusACTIVE
Launch modelFargate only — 2 Fargate tasks running, 0 EC2 / external / managed-instance tasks
Active services2 (both Fargate)
Running / pending tasks2 running · 0 pending
Container Insights✅ ENABLED — cluster setting containerInsights = enabled
Capacity providersNone attached — services use the FARGATE launch type directly
Good: Container Insights is on, so per-task CPU/memory/network metrics and cluster-level dashboards are being collected in CloudWatch.
04

Services & Task Definition

Both services run the same task definition family (reviqueapidevApiServiceTaskDef…:30) and are healthy and at steady state.

ServiceLaunchDesired / RunningDeploy min/max %Circuit breakerTarget groupState
revique-api-dev-service Fargate
PV: LATEST
1 / 1100 / 200 on + rollback reviqu-ApiSe-X9IJ**** STEADY
revique-api-dev-payments-service Fargate
PV: LATEST
1 / 1100 / 200 on + rollback reviqu-ApiSe-ZVNL**** STEADY

Network: each service runs in 2 private subnets (subnet-0****) with 1 security group (sg-0****), assignPublicIp = DISABLED, health-check grace period 60s. Services created 2026-05-13 (api) and 2026-07-09 (payments); latest deployments rolled out COMPLETED.

Task definition — reviqueapidevApiServiceTaskDef… (rev 30)

PropertyValue
Family / revisionreviqueapidevApiServiceTaskDef3B36****:30
RequiresFARGATE · network mode awsvpc
Task sizeCPU 512 (.5 vCPU) · Memory 1024 MiB (1 GB)
RolesExecution role ✅ set · Task role ✅ set (ARNs masked)
Containerapi — essential, port 8080/tcp
Image292****.dkr.ecr.us-east-1.amazonaws.com/cdk-hnb659fds-container-assets-292****-us-east-1:e992****
Env vars (names only)NODE_ENV, PORT, HOST, AWS_REGION, LOG_LEVEL, DATABASE_NAME, DATABASE_SECRET_ARN, DATABASE_SSL_REJECT_UNAUTHORIZED, ALLOWED_ORIGINS, LEGACY_HPT_API_BASE_URL, FLUIDPAY_API_BASE_URL, FLUIDPAY_SANDBOX_PRIVATE_API_KEY_SECRET_ID, PATIENT_FILES_STORAGE_PROVIDER, PATIENT_FILES_S3_BUCKET, PATIENT_FILES_S3_REGION, PATIENT_FILES_UPLOAD_URL_TTL_SECONDS, PATIENT_FILES_DOWNLOAD_URL_TTL_SECONDS, RBAC_TRUSTED_AUTH_CONTEXT_HEADERS, SUPPORT_EMAIL_TO, SUPPORT_EMAIL_FROM (values not shown)
Secrets (ECS secrets[])None injected via secrets; DB & gateway credentials are referenced by Secrets Manager ARN passed as env *_SECRET_ARN / *_SECRET_ID and resolved by the app at runtime
Container health checknone in task def — liveness is enforced by the ALB target-group /health check instead
Log configurationawslogs ✅ → group /revique/revique-api/dev/api, region us-east-1, stream prefix api
Note: both services (api and payments) currently point at the same task-definition family/revision. Confirm this is intended, or whether payments should track its own task def as the two services diverge.
05

Logging & Events

Direct answer to "make sure logs and events are being captured":

CapabilityStatusDetail
Container logs → CloudWatch ✅ YES awslogs driver → /revique/revique-api/dev/api. Active log streams with recent events; ~72 MB stored.
Log retention ✅ 30 days Group has retentionInDays = 30 (not infinite). Reasonable for dev; revisit for prod/compliance needs.
Container Insights (metrics/events) ✅ ENABLED Cluster-level setting on — captures task CPU/memory/network + ECS performance events.
EventBridge rules for ECS state changes ⚠️ NONE 0 EventBridge rules exist in the account/region — no rule captures ECS task/deployment state-change events for alerting or routing.
Logs: captured. Application logs and cluster metrics are being collected — the core of the CEO's "logs and events" ask is satisfied.
Gap (recommendation): there is no EventBridge rule for ECS task-state / deployment-failure events. Container Insights covers metrics, but adding an EventBridge rule on ECS Task State Change / Deployment State Change (target: SNS/Slack) would give proactive notification of crashes, restarts and failed deploys. Review and approve before adding.
06

Auto-scaling

Application Auto Scaling review for the ECS services (service namespace ecs):

ServiceScalable targetMin / MaxPoliciesMetric
revique-api-dev-service❌ none0
revique-api-dev-payments-service❌ none0
Auto-scaling is NOT configured for either service. describe-scalable-targets and describe-scaling-policies both returned empty. Each service runs a fixed desired count of 1 — it will not scale out under load, and a single task failure drops capacity to zero until ECS replaces it.

Recommendation (for CEO approval — not implemented)

  • Register an Application Auto Scaling scalable target per service on ecs:service:DesiredCount, e.g. min 2, max 4 (min 2 also removes the single-task single-point-of-failure).
  • Add a target-tracking policy on ECSServiceAverageCPUUtilization at ~60% (and optionally memory / ALB RequestCountPerTarget).
  • Keep the existing deployment circuit breaker + rollback (already on) for safe rollouts.

These are recommendations only — no scaling resources were created during this review.

07

Load Balancer & Health

PropertyValue
Load balancerrevique-api-dev-alb
Type / schemeapplication · internet-facing · state ACTIVE
DNS namerev****.us-east-1.elb.amazonaws.com (masked)

Target groups

Target groupProtocol : PortHealth checkIntervalThresholdsTarget health
reviqu-ApiSe-X9IJ****HTTP : 80GET /health → 20030s5 healthy / 2 unhealthy✅ healthy
reviqu-ApiSe-ZVNL****HTTP : 8080GET /health → 20030s5 healthy / 2 unhealthy✅ healthy
Good: both target groups have a real /health HTTP check and all registered targets are reporting healthy.
08

ECR & Image

PropertyValue
Repositorycdk-hnb659fds-container-assets-292****-us-east-1
TypeCDK-managed container asset repository (image built & pushed by CDK deploy)
Tag mutability✅ IMMUTABLE — tags can't be overwritten (good supply-chain hygiene)
Scan on push⚠️ DISABLED — images are not automatically vulnerability-scanned on push
Recommendation: enable ECR scan-on-push (basic scanning, or Amazon Inspector enhanced scanning) so container images are checked for known CVEs on every deploy. Immutable tags are already a plus. Review before enabling.
09

Existing Alarms

Alarm typeCountStatus
CloudWatch metric alarms0❌ none
CloudWatch composite alarms0❌ none
No CloudWatch alarms exist in this account/region. Metrics are being collected (Container Insights), but nothing alerts a human when something goes wrong.
Recommendation (for approval): add alarms on ECS service CPU/memory, running-task count < desired, ALB 5XX / unhealthy host count, and target-group health — routed to an SNS topic (email/Slack). Pairs naturally with the EventBridge and auto-scaling recommendations above.
10

Findings & Recommended Next Steps

Prioritized against the CEO's asks. These are review findings — nothing in AWS was changed.

Area (CEO ask)StatusFinding & recommendation
Logs captured✅ Done Container logs → CloudWatch /revique/revique-api/dev/api, 30-day retention, active streams. Consider a longer retention for prod.
Events captured⚠️ Partial Container Insights ✅ on (metrics + ECS perf events). Missing: EventBridge rule for ECS task/deployment state changes → add one to SNS/Slack for proactive alerts.
Auto-scaling❌ Missing Not configured on either service (fixed desired = 1). Recommend scalable target min 2 / max 4 + target-tracking on CPU ~60%. Not implemented — needs approval.
Monitoring / alarms❌ Missing Zero CloudWatch alarms. Add alarms (CPU/mem, task count < desired, ALB 5XX / unhealthy hosts) → SNS. Recommendation.
Image security⚠️ Partial ECR tags immutable ✅, but scan-on-push disabled. Recommend enabling image scanning.
Availability / SPOF⚠️ Partial Desired count 1 per service = single task SPOF (deployment circuit breaker + rollback ✅ mitigate deploys). Min 2 tasks (via the auto-scaling recommendation) removes this.
Load balancer / health✅ Done Internet-facing ALB, /health checks, all targets healthy.
Build modelℹ️ Info Fargate + CDK-managed image & task defs, awsvpc private networking, roles scoped — a clean, reproducible IaC setup.
Summary: logging is solid and the service is healthy behind a working ALB. The three things to act on — all as approvals, not done — are auto-scaling, CloudWatch alarms, and an EventBridge rule for ECS events (plus enabling ECR scan-on-push).
Do-not-publish reminder. The _infra-data/ scratch JSON captured during discovery contains unmasked account IDs, ARNs, subnet/SG IDs and DNS names. Keep it local — do not upload it with this shared site.