AWS VPC Complete Guide: Enterprise Networking Patterns & VPC Peering

Introduction

Amazon Virtual Private Cloud (VPC) is the foundation of AWS networking, providing isolated virtual networks within the AWS cloud. This guide explores VPC types, enterprise network design patterns, VPC peering strategies, and practical Java implementations for production environments.

AWS VPC Fundamentals

What is AWS VPC?

AWS VPC lets you provision a logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define. You have complete control over your virtual networking environment, including selection of your own IP address range, creation of subnets, and configuration of route tables and network gateways.

Types of AWS VPC

1. Default VPC

Every AWS account comes with a default VPC in each AWS Region:

  • CIDR Block: 172.31.0.0/16
  • Pre-configured: Internet Gateway, Route Table, Security Group
  • Public Subnets: One in each Availability Zone
  • Use Cases: Quick testing, simple applications
graph TB
    subgraph "Default VPC (172.31.0.0/16)"
        IGW[Internet Gateway]

        subgraph "AZ-1a"
            PUB1[Public Subnet<br/>172.31.0.0/20]
        end

        subgraph "AZ-1b"
            PUB2[Public Subnet<br/>172.31.16.0/20]
        end

        subgraph "AZ-1c"
            PUB3[Public Subnet<br/>172.31.32.0/20]
        end
    end

    Internet --> IGW
    IGW --> PUB1
    IGW --> PUB2
    IGW --> PUB3

2. Custom VPC

User-defined VPC with custom configuration:

  • Custom CIDR: Any RFC 1918 address range
  • Flexible Design: Public/Private subnet combinations
  • Enhanced Security: Custom security groups and NACLs
  • Use Cases: Production applications, complex architectures

3. VPC Types by Connectivity

VPC TypeInternet AccessUse CasesSecurity Level
Public VPCDirect via IGWWeb applications, API endpointsMedium
Private VPCVia NAT Gateway/InstanceDatabases, internal servicesHigh
Hybrid VPCMixed public/privateMulti-tier applicationsVariable
Isolated VPCNo internet accessHighly sensitive workloadsMaximum

Enterprise Network Design Patterns

1. Three-Tier Architecture

Classic enterprise pattern with presentation, application, and data tiers:

graph TB
    subgraph "Production VPC (10.0.0.0/16)"
        IGW[Internet Gateway]
        NGW[NAT Gateway]

        subgraph "Public Tier (DMZ)"
            ALB[Application Load Balancer]
            WAF[Web Application Firewall]
        end

        subgraph "Private Application Tier"
            APP1[App Server 1]
            APP2[App Server 2]
            APP3[App Server 3]
        end

        subgraph "Private Data Tier"
            RDS[(RDS Database)]
            REDIS[(ElastiCache)]
        end
    end

    Internet --> IGW
    IGW --> ALB
    ALB --> APP1
    ALB --> APP2
    ALB --> APP3
    APP1 --> RDS
    APP2 --> RDS
    APP3 --> RDS
    APP1 --> NGW
    APP2 --> NGW
    APP3 --> NGW
    NGW --> IGW

2. Hub and Spoke Architecture

Centralized connectivity model for multiple VPCs:

graph TB
    subgraph "Hub VPC (Shared Services)"
        HUB[Hub VPC<br/>10.0.0.0/16]
        FW[Network Firewall]
        DNS[Route 53 Resolver]
        MGMT[Management Tools]
    end

    subgraph "Spoke VPCs"
        PROD[Production VPC<br/>10.1.0.0/16]
        DEV[Development VPC<br/>10.2.0.0/16]
        TEST[Test VPC<br/>10.3.0.0/16]
    end

    HUB -.->|VPC Peering| PROD
    HUB -.->|VPC Peering| DEV
    HUB -.->|VPC Peering| TEST

    OnPrem[On-Premises] -->|VPN/Direct Connect| HUB

3. Multi-Account Network Architecture

Enterprise-scale architecture across multiple AWS accounts:

graph TB
    subgraph "Network Account"
        TGW[Transit Gateway]
        DX[Direct Connect]
    end

    subgraph "Production Account"
        PROD_VPC[Production VPC]
    end

    subgraph "Development Account"
        DEV_VPC[Development VPC]
    end

    subgraph "Security Account"
        SEC_VPC[Security VPC]
        FW[Centralized Firewall]
    end

    subgraph "Shared Services Account"
        SHARED_VPC[Shared Services VPC]
        DNS[DNS Services]
        LOGGING[Centralized Logging]
    end

    TGW --> PROD_VPC
    TGW --> DEV_VPC
    TGW --> SEC_VPC
    TGW --> SHARED_VPC
    OnPrem[On-Premises] --> DX
    DX --> TGW

Common Enterprise Network Components

1. Internal Network Segments

 1@Component
 2public class NetworkSegmentManager {
 3
 4    @Value("${aws.vpc.production.cidr}")
 5    private String productionCidr;
 6
 7    @Value("${aws.vpc.development.cidr}")
 8    private String developmentCidr;
 9
10    public enum NetworkTier {
11        PUBLIC("Public", "0.0.0.0/0"),
12        PRIVATE_APP("Private-App", "10.0.0.0/8"),
13        PRIVATE_DATA("Private-Data", "172.16.0.0/12"),
14        MANAGEMENT("Management", "192.168.0.0/16");
15
16        private final String name;
17        private final String defaultCidr;
18
19        NetworkTier(String name, String defaultCidr) {
20            this.name = name;
21            this.defaultCidr = defaultCidr;
22        }
23
24        public String getName() { return name; }
25        public String getDefaultCidr() { return defaultCidr; }
26    }
27
28    public Subnet createSubnet(NetworkTier tier, String availabilityZone) {
29        return Subnet.builder()
30            .vpcId(getVpcId())
31            .cidrBlock(calculateSubnetCidr(tier))
32            .availabilityZone(availabilityZone)
33            .mapPublicIpOnLaunch(tier == NetworkTier.PUBLIC)
34            .tags(Map.of(
35                "Name", tier.getName() + "-" + availabilityZone,
36                "Tier", tier.getName(),
37                "Environment", getCurrentEnvironment()
38            ))
39            .build();
40    }
41}

2. Firewall Integration

 1@Service
 2public class NetworkFirewallService {
 3
 4    private final Ec2Client ec2Client;
 5    private final NetworkFirewallClient firewallClient;
 6
 7    public NetworkFirewallService(Ec2Client ec2Client,
 8                                 NetworkFirewallClient firewallClient) {
 9        this.ec2Client = ec2Client;
10        this.firewallClient = firewallClient;
11    }
12
13    public FirewallPolicy createEnterpriseFirewallPolicy() {
14
15        List<StatelessRule> statelessRules = Arrays.asList(
16            createDenyRule("DENY_ALL_FROM_INTERNET", 1, "0.0.0.0/0"),
17            createAllowRule("ALLOW_HTTPS", 2, "443"),
18            createAllowRule("ALLOW_HTTP", 3, "80")
19        );
20
21        List<StatefulRuleGroup> statefulRules = Arrays.asList(
22            createThreatIntelligenceRules(),
23            createDomainBlockingRules(),
24            createApplicationRules()
25        );
26
27        return FirewallPolicy.builder()
28            .statelessDefaultActions("aws:forward_to_sfe")
29            .statelessFragmentDefaultActions("aws:forward_to_sfe")
30            .statelessRuleGroupReferences(
31                statelessRules.stream()
32                    .map(this::createRuleGroupReference)
33                    .collect(Collectors.toList())
34            )
35            .statefulRuleGroupReferences(
36                statefulRules.stream()
37                    .map(this::createStatefulRuleGroupReference)
38                    .collect(Collectors.toList())
39            )
40            .build();
41    }
42
43    public void deployFirewallToVPC(String vpcId, String firewallPolicyArn) {
44        try {
45            List<SubnetMapping> firewallSubnets = getFirewallSubnets(vpcId);
46
47            CreateFirewallRequest request = CreateFirewallRequest.builder()
48                .firewallName("enterprise-firewall-" + vpcId)
49                .firewallPolicyArn(firewallPolicyArn)
50                .vpcId(vpcId)
51                .subnetMappings(firewallSubnets)
52                .tags(Map.of(
53                    "Environment", "production",
54                    "Purpose", "enterprise-security",
55                    "ManagedBy", "infrastructure-team"
56                ))
57                .build();
58
59            CreateFirewallResponse response = firewallClient.createFirewall(request);
60
61            log.info("Firewall deployed successfully: {}", response.firewall().firewallArn());
62
63            updateRouteTablesForFirewall(vpcId, response.firewall().firewallArn());
64
65        } catch (Exception e) {
66            log.error("Failed to deploy firewall to VPC {}: {}", vpcId, e.getMessage());
67            throw new NetworkFirewallDeploymentException("Firewall deployment failed", e);
68        }
69    }
70}

VPC Peering

What is VPC Peering?

VPC peering connection is a networking connection between two VPCs that enables you to route traffic between them using private IPv4 addresses or IPv6 addresses.

VPC Peering Use Cases

Use CaseDescriptionBenefits
Cross-Region ConnectivityConnect VPCs in different regionsGlobal application architecture
Multi-Account ArchitectureConnect VPCs across AWS accountsOrganizational isolation
Hybrid Cloud IntegrationConnect cloud and on-premisesGradual cloud migration
Microservices CommunicationService-to-service communicationSecure inter-service networking
Data SharingShare databases or data lakesControlled data access

VPC Peering Configuration

  1@Service
  2public class VPCPeeringService {
  3
  4    private final Ec2Client ec2Client;
  5    private final CloudWatchClient cloudWatchClient;
  6
  7    public VPCPeeringService(Ec2Client ec2Client, CloudWatchClient cloudWatchClient) {
  8        this.ec2Client = ec2Client;
  9        this.cloudWatchClient = cloudWatchClient;
 10    }
 11
 12    public VPCPeeringConnection createVPCPeering(VPCPeeringRequest peeringRequest) {
 13
 14        validatePeeringRequest(peeringRequest);
 15
 16        CreateVpcPeeringConnectionRequest request = CreateVpcPeeringConnectionRequest.builder()
 17            .vpcId(peeringRequest.getSourceVpcId())
 18            .peerVpcId(peeringRequest.getTargetVpcId())
 19            .peerRegion(peeringRequest.getTargetRegion())
 20            .peerOwnerId(peeringRequest.getTargetAccountId())
 21            .tagSpecifications(
 22                TagSpecification.builder()
 23                    .resourceType(ResourceType.VPC_PEERING_CONNECTION)
 24                    .tags(
 25                        Tag.builder().key("Name")
 26                           .value(peeringRequest.getConnectionName()).build(),
 27                        Tag.builder().key("Purpose")
 28                           .value(peeringRequest.getPurpose()).build(),
 29                        Tag.builder().key("Environment")
 30                           .value(peeringRequest.getEnvironment()).build()
 31                    )
 32                    .build()
 33            )
 34            .build();
 35
 36        try {
 37            CreateVpcPeeringConnectionResponse response =
 38                ec2Client.createVpcPeeringConnection(request);
 39
 40            VPCPeeringConnection connection = VPCPeeringConnection.builder()
 41                .peeringConnectionId(response.vpcPeeringConnection().vpcPeeringConnectionId())
 42                .sourceVpcId(peeringRequest.getSourceVpcId())
 43                .targetVpcId(peeringRequest.getTargetVpcId())
 44                .status(response.vpcPeeringConnection().status().code().toString())
 45                .build();
 46
 47            if (peeringRequest.isAutoAccept()) {
 48                acceptVPCPeering(connection.getPeeringConnectionId());
 49            }
 50
 51            setupPeeringMonitoring(connection);
 52
 53            log.info("VPC Peering connection created: {}",
 54                    connection.getPeeringConnectionId());
 55
 56            return connection;
 57
 58        } catch (Exception e) {
 59            log.error("Failed to create VPC peering connection: {}", e.getMessage());
 60            throw new VPCPeeringException("VPC Peering creation failed", e);
 61        }
 62    }
 63
 64    public void acceptVPCPeering(String peeringConnectionId) {
 65        try {
 66            AcceptVpcPeeringConnectionRequest request =
 67                AcceptVpcPeeringConnectionRequest.builder()
 68                    .vpcPeeringConnectionId(peeringConnectionId)
 69                    .build();
 70
 71            AcceptVpcPeeringConnectionResponse response =
 72                ec2Client.acceptVpcPeeringConnection(request);
 73
 74            log.info("VPC Peering connection accepted: {}", peeringConnectionId);
 75
 76            waitForPeeringActive(peeringConnectionId);
 77
 78        } catch (Exception e) {
 79            log.error("Failed to accept VPC peering connection {}: {}",
 80                     peeringConnectionId, e.getMessage());
 81            throw new VPCPeeringException("VPC Peering acceptance failed", e);
 82        }
 83    }
 84
 85    public void configureRoutesForPeering(VPCPeeringConfiguration config) {
 86        try {
 87            // Configure routes in source VPC
 88            for (String routeTableId : config.getSourceRouteTableIds()) {
 89                CreateRouteRequest sourceRoute = CreateRouteRequest.builder()
 90                    .routeTableId(routeTableId)
 91                    .destinationCidrBlock(config.getTargetVpcCidr())
 92                    .vpcPeeringConnectionId(config.getPeeringConnectionId())
 93                    .build();
 94
 95                ec2Client.createRoute(sourceRoute);
 96            }
 97
 98            // Configure routes in target VPC
 99            for (String routeTableId : config.getTargetRouteTableIds()) {
100                CreateRouteRequest targetRoute = CreateRouteRequest.builder()
101                    .routeTableId(routeTableId)
102                    .destinationCidrBlock(config.getSourceVpcCidr())
103                    .vpcPeeringConnectionId(config.getPeeringConnectionId())
104                    .build();
105
106                ec2Client.createRoute(targetRoute);
107            }
108
109            log.info("Routes configured for VPC peering connection: {}",
110                    config.getPeeringConnectionId());
111
112        } catch (Exception e) {
113            log.error("Failed to configure routes for peering connection {}: {}",
114                     config.getPeeringConnectionId(), e.getMessage());
115            throw new VPCPeeringException("Route configuration failed", e);
116        }
117    }
118
119    private void setupPeeringMonitoring(VPCPeeringConnection connection) {
120        try {
121            // Create CloudWatch alarms for peering connection health
122            PutMetricAlarmRequest alarmRequest = PutMetricAlarmRequest.builder()
123                .alarmName("vpc-peering-" + connection.getPeeringConnectionId() + "-state")
124                .alarmDescription("Monitor VPC Peering Connection State")
125                .metricName("VPCPeeringConnectionState")
126                .namespace("AWS/VPC")
127                .statistic(Statistic.MAXIMUM)
128                .dimensions(
129                    Dimension.builder()
130                        .name("VPCPeeringConnectionId")
131                        .value(connection.getPeeringConnectionId())
132                        .build()
133                )
134                .period(300)
135                .evaluationPeriods(2)
136                .threshold(1.0)
137                .comparisonOperator(ComparisonOperator.LESS_THAN_THRESHOLD)
138                .treatMissingData("breaching")
139                .build();
140
141            cloudWatchClient.putMetricAlarm(alarmRequest);
142
143        } catch (Exception e) {
144            log.warn("Failed to setup monitoring for peering connection {}: {}",
145                    connection.getPeeringConnectionId(), e.getMessage());
146        }
147    }
148}

VPC Peering Limitations and Considerations

LimitationDescriptionWorkaround
Transitive RoutingNo transitive routing between peered VPCsUse Transit Gateway
Overlapping CIDRsCannot peer VPCs with overlapping IP rangesPlan CIDR blocks carefully
Single Point of FailureOne-to-one relationshipMultiple peering connections
Regional LimitationsCross-region peering has bandwidth limitsConsider data transfer costs

Enterprise VPC Management

1. VPC Lifecycle Management

 1@Service
 2public class VPCLifecycleManager {
 3
 4    private final Ec2Client ec2Client;
 5    private final CloudFormationClient cfnClient;
 6
 7    public VPCCreationResult createEnterpriseVPC(EnterpriseVPCRequest request) {
 8
 9        VPCConfiguration config = VPCConfiguration.builder()
10            .vpcCidr(request.getCidrBlock())
11            .environment(request.getEnvironment())
12            .availabilityZones(request.getAvailabilityZones())
13            .enableDnsSupport(true)
14            .enableDnsHostnames(true)
15            .instanceTenancy("default")
16            .build();
17
18        try {
19            // Create VPC
20            String vpcId = createVPC(config);
21
22            // Create subnets
23            List<String> publicSubnetIds = createPublicSubnets(vpcId, config);
24            List<String> privateSubnetIds = createPrivateSubnets(vpcId, config);
25
26            // Create Internet Gateway
27            String igwId = createInternetGateway(vpcId);
28
29            // Create NAT Gateway
30            String natGatewayId = createNATGateway(publicSubnetIds.get(0));
31
32            // Configure route tables
33            configureRouteTables(vpcId, igwId, natGatewayId,
34                               publicSubnetIds, privateSubnetIds);
35
36            // Setup security groups
37            List<String> securityGroupIds = createDefaultSecurityGroups(vpcId);
38
39            // Enable flow logs
40            enableVPCFlowLogs(vpcId);
41
42            return VPCCreationResult.builder()
43                .vpcId(vpcId)
44                .publicSubnetIds(publicSubnetIds)
45                .privateSubnetIds(privateSubnetIds)
46                .internetGatewayId(igwId)
47                .natGatewayId(natGatewayId)
48                .securityGroupIds(securityGroupIds)
49                .status("CREATED")
50                .build();
51
52        } catch (Exception e) {
53            log.error("Failed to create enterprise VPC: {}", e.getMessage());
54            throw new VPCCreationException("VPC creation failed", e);
55        }
56    }
57
58    public void enableVPCFlowLogs(String vpcId) {
59        try {
60            CreateFlowLogsRequest request = CreateFlowLogsRequest.builder()
61                .resourceType(FlowLogsResourceType.VPC)
62                .resourceIds(vpcId)
63                .trafficType(TrafficType.ALL)
64                .logDestination("arn:aws:logs:" + getCurrentRegion() + ":" +
65                               getCurrentAccountId() + ":log-group:/aws/vpc/flowlogs")
66                .logDestinationType(LogDestinationType.CLOUD_WATCH_LOGS)
67                .logFormat("${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} " +
68                          "${srcport} ${dstport} ${protocol} ${packets} ${bytes} " +
69                          "${windowstart} ${windowend} ${action} ${flowlogstatus}")
70                .tags(Map.of(
71                    "Name", "vpc-flowlogs-" + vpcId,
72                    "Purpose", "security-monitoring"
73                ))
74                .build();
75
76            CreateFlowLogsResponse response = ec2Client.createFlowLogs(request);
77
78            log.info("VPC Flow Logs enabled for VPC {}: {}",
79                    vpcId, response.flowLogIds());
80
81        } catch (Exception e) {
82            log.error("Failed to enable VPC Flow Logs for VPC {}: {}",
83                     vpcId, e.getMessage());
84            throw new VPCConfigurationException("Flow logs configuration failed", e);
85        }
86    }
87}

2. Network Security Best Practices

 1@Component
 2public class NetworkSecurityManager {
 3
 4    public SecurityGroup createTieredSecurityGroups(String vpcId, NetworkTier tier) {
 5
 6        Map<NetworkTier, List<SecurityGroupRule>> tierRules = Map.of(
 7            NetworkTier.PUBLIC, Arrays.asList(
 8                SecurityGroupRule.inbound("443", "0.0.0.0/0", "HTTPS Traffic"),
 9                SecurityGroupRule.inbound("80", "0.0.0.0/0", "HTTP Traffic")
10            ),
11            NetworkTier.PRIVATE_APP, Arrays.asList(
12                SecurityGroupRule.inbound("8080", "10.0.0.0/16", "App Traffic"),
13                SecurityGroupRule.inbound("443", "10.0.0.0/16", "Internal HTTPS")
14            ),
15            NetworkTier.PRIVATE_DATA, Arrays.asList(
16                SecurityGroupRule.inbound("3306", "10.0.1.0/24", "MySQL Traffic"),
17                SecurityGroupRule.inbound("6379", "10.0.1.0/24", "Redis Traffic")
18            )
19        );
20
21        CreateSecurityGroupRequest request = CreateSecurityGroupRequest.builder()
22            .groupName(tier.getName() + "-sg")
23            .description("Security Group for " + tier.getName() + " tier")
24            .vpcId(vpcId)
25            .tags(
26                Tag.builder().key("Name").value(tier.getName() + "-sg").build(),
27                Tag.builder().key("Tier").value(tier.getName()).build()
28            )
29            .build();
30
31        CreateSecurityGroupResponse response = ec2Client.createSecurityGroup(request);
32        String securityGroupId = response.groupId();
33
34        // Add rules for the tier
35        for (SecurityGroupRule rule : tierRules.get(tier)) {
36            addSecurityGroupRule(securityGroupId, rule);
37        }
38
39        return SecurityGroup.builder()
40            .groupId(securityGroupId)
41            .groupName(tier.getName() + "-sg")
42            .tier(tier)
43            .rules(tierRules.get(tier))
44            .build();
45    }
46}

Monitoring and Troubleshooting

VPC Monitoring Dashboard

 1@Service
 2public class VPCMonitoringService {
 3
 4    public void createVPCDashboard(String vpcId) {
 5
 6        String dashboardBody = createDashboardDefinition(vpcId);
 7
 8        PutDashboardRequest request = PutDashboardRequest.builder()
 9            .dashboardName("VPC-Dashboard-" + vpcId)
10            .dashboardBody(dashboardBody)
11            .build();
12
13        cloudWatchClient.putDashboard(request);
14    }
15
16    private String createDashboardDefinition(String vpcId) {
17        return """
18        {
19            "widgets": [
20                {
21                    "type": "metric",
22                    "properties": {
23                        "metrics": [
24                            ["AWS/VPC", "NetworkPacketsIn", "VpcId", "%s"],
25                            [".", "NetworkPacketsOut", ".", "."],
26                            [".", "NetworkBytesIn", ".", "."],
27                            [".", "NetworkBytesOut", ".", "."]
28                        ],
29                        "period": 300,
30                        "stat": "Sum",
31                        "region": "%s",
32                        "title": "VPC Network Traffic"
33                    }
34                }
35            ]
36        }
37        """.formatted(vpcId, getCurrentRegion());
38    }
39}

Conclusion

AWS VPC provides the foundation for secure, scalable cloud networking. Key takeaways:

Best Practices

  • Plan CIDR blocks carefully to avoid overlapping ranges
  • Implement defense in depth with multiple security layers
  • Use VPC Flow Logs for security monitoring and troubleshooting
  • Design for high availability across multiple Availability Zones
  • Implement proper tagging for resource management

When to Use VPC Peering

  • Cross-region connectivity requirements
  • Multi-account architectures
  • Secure service-to-service communication
  • Hybrid cloud integration scenarios

Enterprise Considerations

  • Use Transit Gateway for complex multi-VPC architectures
  • Implement centralized DNS and logging
  • Apply consistent security policies across VPCs
  • Monitor network performance and costs

This comprehensive approach to VPC design and management ensures robust, secure, and scalable cloud networking infrastructure for enterprise applications.