0020. Single VPC per environment
Status: Accepted
Date: 2026-02-22
Context: Whether web frontends and backends use separate VPCs or one VPC per environment with ALB exposure patterns.
Context
For enterprise microservices (target market), we need a clear stance on network
segmentation: one VPC for the whole environment vs. a “frontend” VPC
(internet-facing) and a “backend” VPC (restricted), connected via peering or
PrivateLink.
Decision
We use a single VPC per environment. Exposure is controlled by ALB security
groups: only designated frontends (e.g. ui/* or services with
allowInternetTraffic: true) have ALBs that accept traffic from the internet
(0.0.0.0/0); all other ALBs are internal (traffic only from ECS services in the same
VPC). No separate “frontend” vs “backend” VPC.
Subnet placement (same VPC)
- Public subnets: Only the ALB(s) that are internet-facing (e.g. the one fronting
web-actor with allowInternetTraffic: true). No ECS tasks in public subnets.
- Private subnets: All other ALBs (internal, VPC-only traffic), plus all ECS tasks
(web frontends and backend services). Internal ALBs and tasks are not assigned public
IPs; outbound internet uses the NAT gateway. Traffic path: Internet →
internet-facing ALB (public) → tasks (private); internal traffic: ECS → internal
ALB (private) → tasks (private).
Consequences
- Positive: Simpler operations, lower cost (no peering, single NAT), easier service
discovery and debugging. Tight ALB SGs provide a clear internet boundary; suitable for
many enterprise use cases.
- Tradeoff: If a frontend is compromised, the attacker is in the same VPC as
backends; lateral movement is possible if other controls (SGs, IAM) are
misconfigured.
- Client flexibility: Any client may fork the codebase and introduce a separate
frontend VPC (or other segmentation) if required by compliance or risk. The codebase
is structured (network, security, runtime stacks; export/import decoupling) so that
splitting or reorganising VPCs is a relatively straightforward change.