Skip to content
Back
May 24, 202610 min read

AWS Multi-Account SaaS Architecture

A private, enterprise-grade SaaS architecture using AWS Organizations, Direct Connect, PrivateLink, shared services, Route53 private DNS, GitLab, and Terraform.

AWSPrivateLinkDirect ConnectTerraformSaaS

This architecture evolved into a secure multi-account AWS SaaS model designed around private-only traffic, environment isolation, centralized tooling, and scalable service exposure.

The core traffic path is: client Direct Connect to an access or egress VPC, then peering to ingress VPCs, then Interface Endpoints, PrivateLink, Endpoint Services, and finally application services inside isolated App VPCs.

Account Model

AWS Organizations sits at the top level and provides account lifecycle, governance, SCPs, IAM policy boundaries, and centralized control. Environment accounts are separated by lifecycle, such as production, development, training, and validation.

The shared services account owns core infrastructure such as the Egress VPC and Tooling VPC. The Egress VPC acts as the Direct Connect entry point, centralized outbound internet layer, and endpoint consumer access path. The Tooling VPC hosts CI/CD and internal tooling, including GitLab runners, without exposing those tools directly to client networks.

A separate shared application account hosts centralized services such as Artifactory. Artifactory is exposed through an internal NLB and VPC Endpoint Service, then consumed privately from Tooling and App VPCs through Interface Endpoints.

Environment VPC Pattern

Each environment account contains an Ingress VPC and an App VPC. The Ingress VPC is the endpoint consumer and DNS entry layer. It hosts Interface Endpoints for services such as EKS, MSK, and API Gateway access patterns, plus Route53 Private Hosted Zones.

The App VPC contains application workloads such as EKS, Istio, MSK, RDS, API Gateway integrations, internal Route53 zones, NLBs, and Endpoint Services. This keeps application ownership separate from the client-facing private endpoint layer.

PrivateLink Design

The validated PrivateLink pattern is: consumer VPC to Interface Endpoint, then PrivateLink, Endpoint Service, NLB, ALB, and finally EKS or Istio-backed services.

Endpoint Services are provider-side resources backed by NLBs. Interface Endpoints are consumer-side resources created inside each VPC that needs to consume the service. Interface Endpoints are not shared and are not transitive.

That non-transitive behavior is important. If Tooling, Production, and Development all need access to Artifactory, each consuming VPC creates its own Interface Endpoint to the Artifactory Endpoint Service.

DNS Strategy

The final DNS strategy uses the same internal domain in both App and Ingress VPCs, such as int.arc-one.com. This avoids ALB host-header rewrites and avoids Istio or Envoy translation workarounds.

With the same hostname everywhere, the client uses the name that Istio already expects, for example dashboard.int.arc-one.com. The result is simpler routing, fewer moving parts, and unchanged Istio VirtualServices.

A key Route53 constraint shaped the design: a VPC cannot be associated with two Private Hosted Zones that have the same name. Each VPC can only have one int.arc-one.com zone association path.

Direct Connect Decision

Two Direct Connect patterns were considered. The first kept the existing enterprise-style path using Transit VIF, DX Gateway, Transit Gateway, and VPC attachments. This works well for broader enterprise and multi-cloud routing.

The second created a dedicated SaaS access path using Private VIF, DX Gateway, VGW, Egress VPC, peering, Ingress VPC, Interface Endpoints, PrivateLink, Endpoint Services, and App VPC workloads.

The final recommendation for the SaaS/private endpoint path was the VGW-based model because it reduces Transit Gateway dependency, keeps routing simpler, and aligns better with endpoint-centric SaaS access.

Why VPC Peering Was Required

PrivateLink is cross-VPC, but Interface Endpoint ENIs still live inside the consumer VPC. Clients arriving through the Egress VPC need L3 connectivity to those endpoint ENIs.

That means peering between the Egress VPC and each Ingress VPC is required for this model. The final client path becomes Direct Connect, Egress VPC, VPC peering, Interface Endpoint ENI, PrivateLink, Endpoint Service, App VPC, and finally EKS, MSK, or API Gateway-backed services.

Terraform and GitLab Automation

The deployment model uses GitLab runners with STS AssumeRole to deploy infrastructure cross-account. GitLab does not need direct network connectivity into target VPCs for Terraform operations.

The Terraform architecture uses reusable modules for ingress VPCs, endpoint services, endpoint consumers, endpoint providers, DNS, and environment-specific stacks. Pipeline ordering matters: provider services need to exist before consumers create Interface Endpoints, and DNS setup must follow the endpoint lifecycle.

Final Outcome

The final architecture provides no public exposure for SaaS paths, clear account and environment isolation, centralized tooling, private service exposure through PrivateLink, DNS-based routing simplicity, Istio compatibility without rewrites, and full Terraform automation.

The most important design lesson is that PrivateLink, Direct Connect, DNS, and account boundaries have to be designed together. Treating them as separate implementation details usually creates routing complexity later.