Multi-VPC Network with Transit Gateway
Build a 3-VPC enterprise network with Transit Gateway traffic isolation.
Introduction
30 Second Summary
Think about a company with separate teams for production, development, and shared tools like logging or DNS. These teams all need access to the shared tools, but production and development should never accidentally talk to each other. That is exactly the network isolation problem that enterprises solve every day on AWS.
In this project, you will build a 3-VPC enterprise network connected through a central Transit Gateway, then use custom route tables to enforce traffic isolation between environments while preserving access to shared services.
What You'll Build
You will ping between EC2 instances across three VPCs and watch some pings succeed while others time out, proving that your route table configuration actually blocks cross-environment traffic.
By the end of this project, you'll have:
- A working 3-VPC enterprise network where Production and Development are completely isolated from each other, but both can reach Shared Services through a central Transit Gateway.
- Hands-on proof of route-table-based traffic isolation by running ping tests that succeed to Shared Services and time out between isolated environments.
- A reusable mental model for the "Isolated VPCs with Shared Services" architecture pattern that maps directly to SAP-C02 Domain 1 exam questions on organizational complexity.
- Secret Mission: Add a centralized Network Firewall inspection layer to the Shared Services VPC so all traffic is logged before reaching its destination.
Are there any prerequisites?
You need an AWS account with billing enabled and a SAA-C03-level understanding of VPCs and subnets. If you have passed the AWS Solutions Architect Associate exam or completed hands-on VPC projects before, you are ready to go.
Before We Start
Before we dive into the AWS console, take a moment to commit to what you're building and why. Understanding the architecture goal now makes every configuration decision in the steps ahead click into place.
Create Three VPCs and EC2 Instances
To connect VPCs through a Transit Gateway later, you first need the VPCs themselves. Each VPC needs a unique, non-overlapping address range so the Transit Gateway knows exactly where to send traffic.
Without careful CIDR planning upfront, Transit Gateway routing breaks down. In this step, you'll create three VPCs representing Production, Development, and Shared Services, then launch an EC2 instance in each one to serve as a connectivity test point.
In this step, get ready to:
- Create three VPCs with non-overlapping CIDRs in us-east-1.
- Launch a t2.micro EC2 instance in each VPC for connectivity testing.
- Configure security groups to allow ICMP traffic between VPCs.
Sign in to AWS and create the Production VPC
Each VPC gets its own IP address range (a CIDR block) that does not overlap with the others. This separation is what allows the Transit Gateway to route traffic to the correct destination.
- Sign in to the AWS Management Console at https://console.aws.amazon.com.
- Confirm your region is set to US East (N. Virginia) us-east-1 in the top-right corner of the console.
- Type VPC in the top search bar and select VPC from the results.
- Click Create VPC.
- Under Resources to create, select VPC and more.
- In the Name tag auto-generation field, clear the default and type Prod.
- Set IPv4 CIDR block to 10.1.0.0/16.
- Set Number of Availability Zones to 1.
- Set Number of public subnets to 1.
- Set Number of private subnets to 0.
- Expand Customize subnets CIDR blocks and set the public subnet CIDR to 10.1.1.0/24.
- Set NAT gateways to None.
- Set VPC endpoints to None.
- Click Create VPC at the bottom of the page.
The wizard creates your VPC, subnet, route table, and internet gateway in one go. Wait until the workflow shows all resources as created, then click View VPC.
What did the wizard just create?
The "VPC and more" wizard provisions multiple resources at once: a VPC with CIDR 10.1.0.0/16, a public subnet, a route table with a route to the internet gateway, and the internet gateway itself.
You need the internet gateway and public subnet so you can use EC2 Instance Connect later to SSH into your instances from the browser.
Why non-overlapping CIDRs?
Transit Gateway routes traffic based on destination CIDR. If two VPCs used the same range (e.g., both used 10.1.0.0/16), the Transit Gateway could not tell which VPC a packet should reach. Unique CIDRs make routing deterministic.
Now repeat the process for the Development and Shared Services VPCs.
- Return to the VPC dashboard and click Create VPC again.
- Select VPC and more.
- Set Name tag auto-generation to Dev.
- Set IPv4 CIDR block to 10.2.0.0/16.
- Set Number of Availability Zones to 1, Number of public subnets to 1, and Number of private subnets to 0.
- Expand Customize subnets CIDR blocks and set the public subnet CIDR to 10.2.1.0/24.
- Set NAT gateways to None and VPC endpoints to None.
- Click Create VPC.
- Repeat one more time: click Create VPC from the VPC dashboard.
- Select VPC and more.
- Set Name tag auto-generation to SharedServices.
- Set IPv4 CIDR block to 10.3.0.0/16.
- Set Number of Availability Zones to 1, Number of public subnets to 1, and Number of private subnets to 0.
- Expand Customize subnets CIDR blocks and set the public subnet CIDR to 10.3.1.0/24.
- Set NAT gateways to None and VPC endpoints to None.
- Click Create VPC.
- In the left sidebar, click Your VPCs to see all your VPCs listed.
- Confirm you see three new VPCs with CIDRs 10.1.0.0/16, 10.2.0.0/16, and 10.3.0.0/16.
Rename your VPCs for clarity
The wizard auto-generates names like Prod-vpc, Dev-vpc, and SharedServices-vpc. If you prefer the exact names Prod-VPC, Dev-VPC, and SharedServices-VPC, click the pencil icon next to each VPC's Name tag to edit it.
Don't see three VPCs?
Make sure your region is still set to US East (N. Virginia) in the top-right corner. VPCs are regional resources, so switching regions hides them.
Also check the CIDR column to distinguish your new VPCs from the default VPC (which uses 172.31.0.0/16).
help me troubleshoot why my VPCs aren't showing in the console
Launch EC2 instances in each VPC
You need a test machine inside each VPC to prove network connectivity later. Each instance also needs a security group rule allowing ICMP (ping) traffic from any 10.x.x.x address.
- Type EC2 in the top search bar and select EC2.
- Click Launch instance.
- In the Name field, enter Prod-Instance.
- Under Application and OS Images, confirm Amazon Linux 2023 is selected (it is the default).
- Under Instance type, confirm t2.micro is selected (free tier eligible).
- Under Key pair, select Proceed without a key pair from the dropdown.
- Click Edit next to Network settings.
- In the VPC dropdown, select your Production VPC (look for CIDR 10.1.0.0/16).
- In the Subnet dropdown, select the public subnet (10.1.1.0/24).
- Set Auto-assign public IP to Enable.
- Under Firewall (security groups), select Create security group.
- Remove the default SSH rule by clicking Remove next to it.
- Click Add security group rule.
- Set Type to All ICMP - IPv4.
- Set Source to Custom and enter 10.0.0.0/8.
- Click Launch instance.
You should see a success message confirming your instance is launching.
Why All ICMP from 10.0.0.0/8?
ICMP is the protocol used by the ping command. The source 10.0.0.0/8 covers all three VPC CIDRs (10.1.0.0/16, 10.2.0.0/16, 10.3.0.0/16) in a single rule.
Without this rule, even correct Transit Gateway routing would appear broken because the instance would silently drop ping packets at the security group level.
Now launch the Development and Shared Services instances using the same process.
- Click Launch instance again from the EC2 dashboard.
- Set Name to Dev-Instance.
- Confirm Amazon Linux 2023 and t2.micro are selected.
- Select Proceed without a key pair.
- In Network settings, click Edit and select the Development VPC (CIDR 10.2.0.0/16).
- Select the public subnet (10.2.1.0/24) and set Auto-assign public IP to Enable.
- Create a new security group with the same ICMP rule: Type = All ICMP - IPv4, Source = 10.0.0.0/8.
- Click Launch instance.
- Click Launch instance one more time.
- Set Name to SharedServices-Instance.
- Confirm Amazon Linux 2023 and t2.micro are selected.
- Select Proceed without a key pair.
- In Network settings, click Edit and select the Shared Services VPC (CIDR 10.3.0.0/16).
- Select the public subnet (10.3.1.0/24) and set Auto-assign public IP to Enable.
- Create a new security group with the same ICMP rule: Type = All ICMP - IPv4, Source = 10.0.0.0/8.
- Click Launch instance.
Instance launch failed?
If you see a VPC or subnet error, double-check that you selected the correct VPC in the Network settings section. The subnet dropdown only shows subnets belonging to the selected VPC.
If you see a quota error, your account may have hit the default EC2 instance limit. Check the Service Quotas console for your us-east-1 instance limits.
help me troubleshoot my EC2 instance launch failure
Note private IPs and verify all instances are running
You will use each instance's private IP address to test ping connectivity through the Transit Gateway in later steps.
- In the EC2 console left sidebar, click Instances.
- Wait until all three instances (Prod-Instance, Dev-Instance, SharedServices-Instance) show Running in the Instance state column.
- Click on Prod-Instance to open its details.
- In the Details tab, find Private IPv4 address and note down this value.
- Repeat for Dev-Instance and SharedServices-Instance, noting each private IP.
What should I see?
Each instance's private IP will be in its VPC's subnet range. For example, Prod-Instance will have an IP like 10.1.1.x, Dev-Instance will be 10.2.1.x, and SharedServices-Instance will be 10.3.1.x.
Before you move on, do you think these three instances can ping each other right now?
They cannot. Each VPC is completely isolated. There is no network path between them yet. That is exactly the problem the Transit Gateway solves in the next step.
Instance stuck in Pending?
Instances typically take 30-60 seconds to reach Running state. Click the refresh icon in the instances list to check for updates.
If an instance stays in Pending for more than 2 minutes, check the Status checks tab for error details.
help me figure out why my EC2 instance is stuck in pending state
Your three VPCs and instances are ready. Next up, you'll create the Transit Gateway and connect all three VPCs to it, proving that a flat connection lets everything talk to everything.
Create the Transit Gateway and Attach VPCs
You have three VPCs sitting in the same region, but they cannot communicate with each other at all. Each VPC is its own isolated network bubble.
To connect them, you need a central router that all three VPCs can plug into. That router is an AWS Transit Gateway. In this step, you will create the Transit Gateway, attach all three VPCs, and prove that traffic flows between them.
In this step, get ready to:
- Create a Transit Gateway as the central network hub.
- Attach all three VPCs to the Transit Gateway.
- Add routes and test connectivity between VPCs.
Create the Transit Gateway
The Transit Gateway is a regional router managed by AWS. When you create one, AWS automatically sets up a default route table inside it that lets all attached VPCs see each other.
- In the AWS Management Console, make sure you are in the us-east-1 region.
- In the navigation pane on the left, choose Transit Gateways (under the Transit Gateway section of the VPC console).
- Click Create transit gateway.
- For Name tag, enter Enterprise-TGW.
- For Amazon side ASN, leave the default value of 64512.
- Confirm that DNS support is enabled.
- Confirm that Default route table association is enabled.
- Confirm that Default route table propagation is enabled.
- Click Create transit gateway.
The Transit Gateway state shows Pending initially. Wait 2-3 minutes until the state changes to Available before continuing.
What is a Transit Gateway?
A Transit Gateway is a regional network hub that lets you connect multiple VPCs through a single gateway instead of creating individual peering connections between each pair.
With 3 VPCs, you would need 3 peering connections for full mesh connectivity. With 10 VPCs, you would need 45. A Transit Gateway centralizes this into a single attachment per VPC.
What is an ASN?
An ASN (Autonomous System Number) identifies your Transit Gateway on a network for BGP routing. The default 64512 is a private ASN reserved for internal use. For this project, the default is all you need.
Still seeing Pending after 5 minutes?
Transit Gateway creation typically takes 2-3 minutes. If it remains in Pending state for longer than 5 minutes, refresh the console page. If the state shows Failed, check that your account has permission to create Transit Gateways and try again.
Need help? Why is my Transit Gateway stuck in Pending state?
Attach your VPCs to the Transit Gateway
Each VPC needs its own attachment to the Transit Gateway. The attachment tells the Transit Gateway which subnet to use for routing traffic into that VPC.
You will create three attachments, one for each VPC. Start with Prod-VPC.
- In the navigation pane, choose Transit Gateway Attachments.
- Click Create transit gateway attachment.
- For Name tag, enter Prod-Attach.
- For Transit gateway ID, select Enterprise-TGW.
- For Attachment type, choose VPC.
- For VPC ID, select Prod-VPC.
- For Subnet IDs, select the public subnet in the 10.1.1.0/24 range.
- Click Create transit gateway attachment.
Now repeat for Dev-VPC and SharedServices-VPC.
- Click Create transit gateway attachment again.
- For Name tag, enter Dev-Attach.
- For Transit gateway ID, select Enterprise-TGW.
- For Attachment type, choose VPC.
- For VPC ID, select Dev-VPC.
- For Subnet IDs, select the public subnet in the 10.2.1.0/24 range.
- Click Create transit gateway attachment.
- Click Create transit gateway attachment one more time.
- For Name tag, enter SharedServices-Attach.
- For Transit gateway ID, select Enterprise-TGW.
- For Attachment type, choose VPC.
- For VPC ID, select SharedServices-VPC.
- For Subnet IDs, select the public subnet in the 10.3.1.0/24 range.
- Click Create transit gateway attachment.
Wait until all three attachments show Available in the State column. This typically takes 1-2 minutes per attachment.
Why one subnet per attachment?
The Transit Gateway places a network interface in the subnet you select. Traffic entering or leaving that VPC through the Transit Gateway flows through this interface. You must specify one subnet from each Availability Zone to be used by the Transit Gateway to route traffic.
Don't see your VPC in the dropdown?
Make sure you are in the us-east-1 region. Transit Gateway attachments can only connect to VPCs in the same region as the Transit Gateway. Also confirm the Transit Gateway state is Available before creating attachments.
Still stuck? Help me troubleshoot my Transit Gateway VPC attachment
Update VPC route tables and test connectivity
The attachments are in place, but traffic still cannot flow. Each VPC's route table only knows about its own local CIDR block. You need to add a route telling each VPC to send non-local 10.x.x.x traffic to the Transit Gateway.
Start with Prod-VPC's route table.
- In the VPC console navigation pane, choose Route tables.
- Select the route table associated with Prod-VPC's public subnet.
- Choose the Routes tab, then click Edit routes.
- Click Add route.
- For Destination, enter 10.0.0.0/8.
- For Target, choose Transit Gateway, then select your Enterprise-TGW.
- Click Save changes.
Now repeat the same route addition for Dev-VPC and SharedServices-VPC.
- Select the route table associated with Dev-VPC's public subnet.
- Choose Edit routes, click Add route.
- Enter 10.0.0.0/8 as the Destination and select Enterprise-TGW as the Target.
- Click Save changes.
- Select the route table associated with SharedServices-VPC's public subnet.
- Repeat the same steps: add route 10.0.0.0/8 pointing to Enterprise-TGW.
- Click Save changes.
What does this route do?
The destination 10.0.0.0/8 covers all IP addresses from 10.0.0.0 to 10.255.255.255. This tells each VPC: for any traffic headed to a 10.x.x.x address that is not in my own CIDR, forward it to the Transit Gateway.
The Transit Gateway then checks its own route table to decide which VPC attachment to forward the packet to. Because you enabled default route table propagation, all three VPC CIDRs are automatically advertised inside the Transit Gateway.
Now it is time to test. Before you run the ping, think about what you expect to happen. All three VPCs share the same default Transit Gateway route table with all routes propagated. Do you think Prod-Instance can reach SharedServices-Instance?
- Navigate to the EC2 console.
- Select Prod-Instance from your instances list.
- Click Connect, then choose the EC2 Instance Connect tab.
- Click Connect to open a browser-based terminal session.
- In the terminal, ping your SharedServices-Instance using its private IP:
ping -c 4 [[SHARED_SERVICES_IP="your SharedServices-Instance private IP"]]
You should see successful replies with round-trip times. This proves that Prod-VPC can reach SharedServices-VPC through the Transit Gateway.
Now try pinging Dev-Instance from the same Prod-Instance terminal:
ping -c 4 [[DEV_INSTANCE_IP="your Dev-Instance private IP"]]
This also succeeds. Production can reach Development directly. In an enterprise environment, this is a security problem. Production workloads should never have a network path to Development.
Why is flat routing a problem?
Right now, all three attachments share the same default Transit Gateway route table. Every VPC can see every other VPC. This is called "flat" routing.
In a real enterprise, you want Production isolated from Development so a misconfigured dev service cannot accidentally call production databases. The fix is creating custom Transit Gateway route tables that enforce selective propagation. You will do exactly that in the next step.
Ping timing out?
If your pings are not getting through, check these common causes:
- Confirm that the security group on the target instance allows All ICMP - IPv4 from source 10.0.0.0/8.
- Verify that the VPC route table for both the source and destination VPCs has the 10.0.0.0/8 route pointing to the Transit Gateway.
- Check that all three Transit Gateway attachments show Available state (not Pending or Failed).
Still stuck? Help me debug why my ping between VPCs through Transit Gateway is timing out
Your Transit Gateway is live and all three VPCs can talk to each other. Next up, you will break this flat connectivity on purpose by creating custom route tables that isolate Production from Development while keeping Shared Services accessible to both.
Implement Traffic Isolation with Custom Route Tables
In the previous step, you proved that all three VPCs can talk to each other through the default Transit Gateway route table. That flat connectivity is a security problem.
In an enterprise, Production should never reach Development directly. You need custom route tables that enforce the "Isolated VPCs with Shared Services" pattern: Prod and Dev each reach SharedServices, but cannot reach each other.
In this step, get ready to:
- Create two custom Transit Gateway route tables to replace the default flat routing.
- Configure selective route propagation so Prod and Dev only learn the SharedServices route.
- Verify that Prod-to-Dev traffic is blocked while SharedServices access still works.
Create custom Transit Gateway route tables
The default route table propagates every attachment's CIDR to every other attachment. To isolate environments, you need two separate route tables with different propagation rules.
- In the VPC console left navigation, click Transit Gateway Route Tables.
- Click Create transit gateway route table.
- For Name tag, enter RT-Isolated.
- For Transit gateway ID, select Enterprise-TGW.
- Click Create transit gateway route table.
You should see RT-Isolated appear in the route tables list.
- Repeat the process to create a second route table named RT-Shared, also associated with Enterprise-TGW.
You should now see both RT-Isolated and RT-Shared listed alongside the default route table.
Why two route tables?
RT-Isolated is for the Production and Development attachments. It will only contain a route to SharedServices, so Prod and Dev can never discover each other's CIDR.
RT-Shared is for the SharedServices attachment. It will contain routes to both Prod and Dev, so SharedServices can respond to traffic from either environment.
Now disassociate all three attachments from the default route table so they stop using flat routing.
- Select the default route table (it has no custom name tag).
- In the lower section, click the Associations tab.
- Select Prod-Attach and click Delete association.
- Confirm by clicking Delete association.
- Repeat for Dev-Attach and SharedServices-Attach.
The default route table's Associations tab should now show no associations.
Don't see your attachments listed?
Make sure you selected the default route table, not one of your new custom tables. The default table is the one without a Name tag (or with a system-generated name).
If an attachment shows state "disassociating", wait 30 seconds and refresh. Help me find and disassociate attachments from the default route table.
Configure RT-Isolated for environment segregation
RT-Isolated is where Prod and Dev live. By only propagating SharedServices into this table, Prod and Dev will only see a route to 10.3.0.0/16. They will have no route to each other.
- In the Transit Gateway Route Tables list, select RT-Isolated.
- Click the Associations tab in the lower section.
- Click Create association.
- Select Prod-Attach from the dropdown and click Create association.
- Repeat to create a second association for Dev-Attach.
Both Prod-Attach and Dev-Attach should now show as associated in the Associations tab.
- Now enable route propagation from SharedServices only. With RT-Isolated still selected, click Actions, then Create propagation.
- On the Create propagation page, select SharedServices-Attach.
- Click Create propagation.
Why NOT propagate Prod-Attach or Dev-Attach here?
If you propagated Prod-Attach into RT-Isolated, Dev-Attach would learn a route to 10.1.0.0/16 (and vice versa). That would break isolation. By propagating only SharedServices-Attach, both Prod and Dev see only one route: 10.3.0.0/16.
- Click the Routes tab on RT-Isolated to confirm the propagated route appeared.
You should see one route: 10.3.0.0/16 with target SharedServices-Attach and type "propagated".
Route not appearing?
Propagated routes can take 10-20 seconds to appear. Click the refresh icon in the Routes tab. If still empty, verify you created the propagation on the correct route table (RT-Isolated, not RT-Shared or the default).
Help me troubleshoot why my propagated route is not showing up in RT-Isolated.
Configure RT-Shared for bidirectional shared access
RT-Shared needs routes to both Prod and Dev so SharedServices can send response traffic back to either environment.
- In the Transit Gateway Route Tables list, select RT-Shared.
- Click the Associations tab and click Create association.
- Select SharedServices-Attach and click Create association.
SharedServices-Attach now shows as associated with RT-Shared.
- Click Actions, then Create propagation.
- Select Prod-Attach and click Create propagation.
- Repeat: click Actions, Create propagation, select Dev-Attach, and click Create propagation.
- Click the Routes tab on RT-Shared to confirm the propagated routes appeared.
You should see two routes: 10.1.0.0/16 pointing to Prod-Attach, and 10.2.0.0/16 pointing to Dev-Attach. Both marked as "propagated".
How does the full pattern work?
RT-Isolated only knows about SharedServices (10.3.0.0/16). When Prod sends a packet to 10.2.0.0/16 (Dev), the Transit Gateway looks up RT-Isolated, finds no matching route, and drops the packet.
RT-Shared knows about both Prod (10.1.0.0/16) and Dev (10.2.0.0/16). When SharedServices sends a response back to either VPC, the Transit Gateway finds the route and delivers the packet.
Now test that isolation actually works. Before you run the ping, think about what you expect to happen. The Prod-Instance is associated with RT-Isolated, which only has a route to 10.3.0.0/16. What do you think will happen when you ping the Dev-Instance at 10.2.x.x?
- Navigate to the EC2 console and select Prod-Instance.
- Click Connect, then use the EC2 Instance Connect tab and click Connect.
- First, test SharedServices access by pinging the SharedServices-Instance private IP (the one you noted earlier):
ping -c 4 10.3.1.x
Replace 10.3.1.x with the actual private IP of SharedServices-Instance. You should see successful replies.
- Now test isolation by pinging the Dev-Instance private IP:
ping -c 4 10.2.1.x
Replace 10.2.1.x with the actual private IP of Dev-Instance. This should time out with no replies. That is the isolation working.
- Confirm the same pattern from the other direction. Open a new EC2 Instance Connect session on Dev-Instance.
- Ping the Prod-Instance private IP:
ping -c 4 10.1.1.x
This also times out. Dev cannot reach Prod, and Prod cannot reach Dev. Both can still reach SharedServices.
Ping to SharedServices also timing out?
If SharedServices pings fail too, the attachments may still be disassociating from the old table or not yet fully associated with the new table. Wait 30 seconds and try again.
Also verify you created the propagation on the correct table: SharedServices-Attach should propagate into RT-Isolated (not the other way around). Check the Propagations tab on RT-Isolated to confirm SharedServices-Attach is listed.
Help me figure out why my ping to SharedServices is failing after I set up custom route tables.
Your network isolation is working. The Transit Gateway is enforcing route-table-based segmentation. Next up, you will run a comprehensive connectivity matrix to prove every direction of the architecture behaves as expected.
Validate the Architecture
Your custom route tables are in place. Production and Development are associated with RT-Isolated (which only knows how to reach Shared Services), while Shared Services sits on RT-Shared (which knows how to reach both).
An architecture without proven testing is just a diagram. In this step, you will run ping tests from each VPC to confirm that isolation actually works. You need both the positive case (shared services reachable) and the negative case (cross-environment traffic blocked).
In this step, get ready to:
- Test connectivity from Production to Shared Services and Development.
- Test connectivity from Development to Shared Services and Production.
- Test connectivity from Shared Services to both Production and Development.
Test connectivity from Production
Your first test proves two things at once: that Production can reach Shared Services (the positive case) and that Production cannot reach Development (the negative case, proving isolation).
- In the AWS Console, navigate to the EC2 service.
- Select Instances in the left sidebar.
- Select the checkbox next to Prod-Instance.
- Click Connect at the top of the page.
- On the Connect to instance page, keep the EC2 Instance Connect tab selected and click Connect.
A terminal session opens in your browser, connected directly to Prod-Instance.
- Test that Production can reach Shared Services by running this ping command:
ping -c 4 [[SHARED_SERVICES_IP="your SharedServices-Instance private IP"]]
You should see four successful replies with round-trip times. This confirms that Prod-Instance can communicate with SharedServices-Instance through the Transit Gateway.
Now for the critical isolation test. Before you run the next command, predict what you think will happen when Production tries to reach Development.
- Test that Production cannot reach Development by running:
ping -c 4 [[DEV_INSTANCE_IP="your Dev-Instance private IP"]]
The ping times out with no replies. This is your isolation working. RT-Isolated has no route to 10.2.0.0/16 because Dev-Attach does not propagate into its own route table. Production literally has no path to Development.
Why does the ping time out instead of returning an error?
When there is no route, the Transit Gateway silently drops the packet. There is no ICMP "destination unreachable" message sent back because the packet never reaches a host that could generate one. The ping command waits for a reply that never comes, then reports 100% packet loss.
Ping to SharedServices-Instance also timing out?
Check that your SharedServices-Instance security group allows All ICMP - IPv4 from source 10.0.0.0/8. Also verify the SharedServices VPC route table has a route for 10.0.0.0/8 pointing to Enterprise-TGW.
Confirm in Transit Gateway Route Tables that RT-Isolated shows a propagated route for 10.3.0.0/16 pointing to SharedServices-Attach.
help me troubleshoot why my Prod-Instance cannot ping SharedServices-Instance through Transit Gateway
Test connectivity from Development
Development shares the same RT-Isolated route table as Production, so you should see the mirror result: Shared Services reachable, Production blocked.
- Close the Prod-Instance terminal tab or navigate back to the EC2 Instances page.
- Select the checkbox next to Dev-Instance.
- Click Connect, keep EC2 Instance Connect selected, and click Connect.
- Test that Development can reach Shared Services by running:
ping -c 4 [[SHARED_SERVICES_IP="your SharedServices-Instance private IP"]]
Four successful replies confirm Dev-Instance can reach SharedServices-Instance.
- Test that Development cannot reach Production by running:
ping -c 4 [[PROD_INSTANCE_IP="your Prod-Instance private IP"]]
The ping times out again. Isolation is confirmed in both directions. Neither Production nor Development can reach each other.
Test connectivity from Shared Services
The final test proves that Shared Services can respond to both environments. RT-Shared has propagated routes for both 10.1.0.0/16 and 10.2.0.0/16, so bidirectional communication should work.
- Close the Dev-Instance terminal tab or navigate back to the EC2 Instances page.
- Select the checkbox next to SharedServices-Instance.
- Click Connect, keep EC2 Instance Connect selected, and click Connect.
- Test that Shared Services can reach Production by running:
ping -c 4 [[PROD_INSTANCE_IP="your Prod-Instance private IP"]]
Four successful replies. Shared Services can reach Production.
- Test that Shared Services can reach Development by running:
ping -c 4 [[DEV_INSTANCE_IP="your Dev-Instance private IP"]]
Four successful replies again. Shared Services acts as the bridge that both environments can access, while those environments remain invisible to each other.
What did you just prove?
You validated the complete "Isolated VPCs with Shared Services" pattern. Production and Development are fully isolated from each other. Both can reach Shared Services. Shared Services can respond to both. This is the exact architecture that the SAP-C02 exam tests in Domain 1 (Organizational Complexity) questions.
The key mechanism is selective route propagation. RT-Isolated only has routes propagated from SharedServices-Attach. Since neither Prod-Attach nor Dev-Attach propagates into RT-Isolated, there is simply no route between them.
Extra for Experts: Why not use security groups for isolation?
Security groups block traffic at the instance level, but the packets still traverse the network. With Transit Gateway route table isolation, packets between Prod and Dev never even get routed. There is no path in the routing layer at all. This is defense-in-depth: even if someone misconfigures a security group, the network architecture itself prevents the traffic.
Secret mission
Add Network Firewall Inspection
In a real enterprise, traffic flowing to Shared Services should be inspected before it reaches any workload. Can you add a centralized AWS Network Firewall that inspects all inbound traffic to SharedServices-VPC, proving the packets flow through the firewall before reaching the instance?
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses paid AWS services that charge by the hour, so ongoing costs accumulate even when you are not actively working.
Cost warning
Transit Gateway charges $0.05 per VPC attachment per hour. With 3 attachments, that is $0.15/hr or approximately $3.60/day.
If you completed the Secret Mission, AWS Network Firewall adds approximately $0.395 per endpoint per hour on top of Transit Gateway costs. Delete all resources immediately after completing the project to avoid ongoing charges.
Resources you used:
- 3 EC2 instances (Prod-Instance, Dev-Instance, SharedServices-Instance).
- 3 Transit Gateway VPC attachments (Prod-Attach, Dev-Attach, SharedServices-Attach).
- 1 Transit Gateway (Enterprise-TGW).
- 2 custom Transit Gateway route tables (RT-Isolated, RT-Shared).
- 3 VPCs (Prod-VPC, Dev-VPC, SharedServices-VPC) with subnets, route tables, and internet gateways.
- AWS Network Firewall with stateful rule group (Secret Mission only).
Keep everything running
No action needed. Choose this if you are still actively building or want to experiment further with Transit Gateway routing.
- Your Transit Gateway attachments will continue charging $0.15/hr ($3.60/day) while active.
- EC2 t2.micro instances are free tier eligible (up to 750 hours/month across all t2.micro instances in the account).
- If you deployed the Network Firewall, it adds approximately $0.395/hr ($9.48/day) on top of Transit Gateway costs.
Pause - I'll come back to this later
Stop the EC2 instances to save on compute, but note that Transit Gateway and Network Firewall charge by the hour regardless of traffic. There is no way to pause these services without deleting them.
- In the EC2 console, select each instance (Prod-Instance, Dev-Instance, SharedServices-Instance), then choose Instance state > Stop instance.
- Stopped instances do not incur compute charges but their EBS volumes remain (minimal cost).
- Transit Gateway attachments continue charging $0.15/hr even with stopped instances. Consider deleting all resources if you will not return within a few hours.
Delete - I don't want to use this again
Remove all project resources to stop all charges. Follow this order carefully because some resources depend on others.
- Delete the Network Firewall first (Secret Mission only): in the VPC console, go to Network Firewall > Firewalls, select your firewall, and choose Delete. Wait for deletion to complete before proceeding.
- Delete the firewall rule group: in the VPC console, go to Network Firewall > Network Firewall rule groups, select your stateful rule group, and choose Delete.
- Terminate all 3 EC2 instances: in the EC2 console, select Prod-Instance, Dev-Instance, and SharedServices-Instance, then choose Instance state > Terminate instance.
- Delete Transit Gateway attachments: in the VPC console, go to Transit Gateway Attachments, select Prod-Attach, Dev-Attach, and SharedServices-Attach, then choose Actions > Delete transit gateway attachment. Wait until all attachments show Deleted state.
- Delete the Transit Gateway route tables: go to Transit Gateway Route Tables, select RT-Isolated and RT-Shared, then choose Actions > Delete transit gateway route table.
- Delete the Transit Gateway: go to Transit Gateways, select Enterprise-TGW, then choose Actions > Delete transit gateway. Wait for the state to show Deleted.
- Delete all 3 VPCs: go to Your VPCs, select Prod-VPC, and choose Actions > Delete VPC. This also deletes associated subnets, route tables, and internet gateways. Repeat for Dev-VPC and SharedServices-VPC.
VPC deletion fails?
If a VPC cannot be deleted, it still has a dependency. Confirm that all EC2 instances in that VPC are terminated and all Transit Gateway attachments are in Deleted state. Network interfaces created by the Network Firewall may take a few minutes to release after firewall deletion.
Help me identify what resource is blocking my VPC deletion
That's a Wrap!
That's a Wrap!
Nice work! You just built a production-grade multi-VPC enterprise network with enforced traffic isolation using AWS Transit Gateway.
You've learned how to:
- Build a 3-VPC enterprise network topology connected via a central Transit Gateway, implementing the "Isolated VPCs with Shared Services" pattern using custom route tables and selective route propagation.
- Prove network isolation works by testing connectivity between EC2 instances. Production and Development cannot reach each other, but both reach Shared Services.
- Understand the architectural trade-off between flat routing (simple but insecure) and segmented routing (complex but secure) that the SAP-C02 exam tests in Domain 1.
- Secret Mission: Added centralized traffic inspection via AWS Network Firewall with appliance mode routing, proving inspected packets flow through the firewall before reaching the Shared Services instance.
Ready to quiz yourself?