Status: Accepted Date: 2026-04-07 Context: Optional TLS on internal ALBs for in-VPC east-west traffic, versus HTTP behind security groups and private subnets.
The runtime uses an internal-facing Application Load Balancer in private subnets for service-to-service and browser-to-API paths that are routed by hostname and path rules. Traffic stays inside the VPC between Fargate tasks and the internal ALB.
TLS on the public ALB is required for browser-facing HTTPS and is implemented (ACM certificate,
HTTPS listener, HTTP to HTTPS redirect). That work establishes a repeatable pattern: ACM in the same region
as the ALB, listeners, and task client configuration using the correct scheme (for example CORS
Origin matching https for the public hostname).
TLS on the internal ALB adds encryption in transit for east-west hops and raises the bar against passive observation or trivial in-VPC manipulation of cleartext. It does not replace service authentication, stateless tokens, or least-privilege IAM; those controls prove who is calling. Defense in depth combines identity with confidentiality on the wire.
Operational reality: not every deployment has strict PII, regulated workloads, or organizational mandates for encrypt everything inside the VPC. Internal HTTP behind security groups and private subnets is a common AWS pattern. Rolling out internal HTTPS on the listener is incremental once public TLS is understood: ACM-issued certificate for a resolvable internal hostname, or a private CA-issued certificate where required, 443 listener on the internal ALB, security group ingress on 443, and https:// base URLs in REST clients and health checks where applicable. That still leaves the ALB → target hop as a separate decision (see below).
Application Load Balancers terminate TLS on the listener when you use an HTTPS listener. Traffic from the load balancer to registered targets uses whatever protocol the target group is configured for.
Baseline Forge CDK: all application target groups use protocol: HTTP to ECS tasks on the
container port. The public ALB uses an HTTPS listener toward clients and forwards to those HTTP
target groups. So today:
| Segment | Encrypted in baseline? |
|---|---|
| Client → public ALB | Yes (HTTPS listener, ACM on the ALB). |
| Public ALB → ECS task | No (HTTP target group within the VPC). |
| Task → internal ALB → task | No (HTTP throughout). |
Implication: Turning on an HTTPS listener on the internal ALB encrypts caller → internal ALB only. It does not, by itself, encrypt internal ALB → Fargate. Full encryption on that last hop requires HTTPS target groups (and tasks serving TLS, with certificate trust and health checks aligned), or a service mesh / mTLS pattern (for example AWS App Mesh, Istio), or other designs outside the baseline ADR.
This ADR avoids implying that listener-only HTTPS equals end-to-end encryption to the task. Reviewers and customer teams should treat infrastructure observation between ALB and task as out of scope for listener TLS alone.
Baseline CDK keeps the internal ALB on HTTP for listeners between tasks and the internal ALB.
This matches the current addInternalAlbListener shape (http:// to the internal ALB DNS name).
HTTPS on the internal ALB is optional and customer-owned when compliance, threat model, or policy require east-west encryption. Teams may adopt it by following the same TLS pattern already proven on the public ALB (certificate, listeners, clients, and scheme-correct configuration such as CORS or callback URLs where relevant).
No requirement that every Forge deployment enable internal TLS. The reference implementation demonstrates public-edge TLS; internal TLS remains an extension for clients who need it.
The baseline choice is deliberately HTTP on the internal ALB. The following thresholds make when to stay on that posture vs when to add internal TLS explicit for security reviewers and customer teams. They do not change the Decision: CDK still ships HTTP internally until a team opts in.
Internal HTTP on the private ALB is a reasonable posture when (all are generally true for the deployment):
Internal HTTPS (or mTLS) on the private ALB is strongly recommended when any of the following apply:
Customer-owned action: teams that hit the strongly recommended row should plan HTTPS (or mTLS) on the internal listener using the same certificate and listener pattern as the public ALB, plus https:// internal base URLs for REST clients and any health checks that target that listener. If policy requires encryption all the way to the task, they must also plan HTTPS target groups (and TLS on the application) or mesh / mTLS, as described in ALB TLS termination and the hop to targets above.
Positive: Simpler baseline operations (single scheme for internal URLs, no extra cert lifecycle for the internal hostname unless needed); flexibility for customers with different compliance bars; clear separation between internet risk (must encrypt) and VPC risk (policy-driven).
Explicit gap: Baseline east-west traffic to the internal ALB is not TLS-protected. See Guidance above for when that is acceptable vs when customer teams should treat internal HTTPS (or mTLS) as expected, not optional.
Listener TLS alone: Even the public ALB does not use HTTPS to targets in baseline; ALB → task is HTTP. Internal listener HTTPS would mirror that split. Do not equate ALB HTTPS with end-to-end encryption to ECS without target group and application changes (or mesh). See ALB TLS termination and the hop to targets.
Security posture: Zero-trust service authentication and stateless conversations remain authoritative for caller identity; internal TLS is an additional layer for payload protection on the network path, not a substitute for authn or authz.