Hybrid Cloud Strategies with AWS: Architecture Patterns and Best Practices
Design robust hybrid cloud architectures using AWS Outposts, Direct Connect, and Site-to-Site VPN for seamless on-premise and cloud integration
Introduction
Hybrid cloud architectures combine on-premise infrastructure with cloud resources, offering flexibility, gradual migration paths, and the ability to meet specific regulatory or technical requirements. AWS provides comprehensive services for building secure, high-performance hybrid cloud solutions.
This guide explores AWS hybrid cloud strategies, architecture patterns, connectivity options, and real-world use cases for organizations maintaining both on-premise and cloud infrastructure.
What You’ll Learn:
- AWS hybrid cloud service portfolio (Outposts, Direct Connect, VPN)
- Network architecture patterns for hybrid connectivity
- When hybrid cloud makes sense vs. full cloud migration
- Latency considerations and performance optimization
- Cost comparison: Direct Connect vs. Site-to-Site VPN
- Terraform examples for hybrid infrastructure
- Data gravity and regulatory compliance scenarios
AWS Hybrid Cloud Services
AWS Outposts
Description: AWS infrastructure deployed in your on-premise data center
Key Features:
- Same AWS APIs, tools, and services as public cloud
- Local compute and storage in your facility
- Managed by AWS (hardware, software, updates)
- Seamless integration with AWS regions
Hardware Options:
- Outposts rack: 42U rack with compute, storage, networking
- Outposts servers: 1U or 2U servers for smaller deployments
Use Cases:
- Ultra-low latency requirements (< 1ms)
- Data residency and sovereignty mandates
- Local data processing before cloud upload
- Legacy systems requiring on-premise connectivity
- Factory/manufacturing edge computing
Supported Services:
- EC2, EBS, S3, RDS, ECS, EKS
- VPC, ELB, EMR
- Local Gateway for on-premise connectivity
AWS Direct Connect
Description: Dedicated network connection from on-premise to AWS
Key Features:
- Private, dedicated bandwidth (1 Gbps or 10 Gbps)
- Consistent network performance
- Reduced data transfer costs
- Support for multiple VPCs via Virtual Interfaces (VIFs)
Connection Types:
- Dedicated Connection: Direct physical connection to AWS
- Hosted Connection: Through AWS Direct Connect Partner
Use Cases:
- High-bandwidth workloads
- Consistent, predictable performance needed
- Large-scale data migration
- Hybrid cloud with frequent data sync
- Compliance requiring private connectivity
Pricing Model:
- Port hour fees (fixed)
- Data transfer out fees (reduced vs. internet)
- No inbound data transfer fees
AWS Site-to-Site VPN
Description: Encrypted VPN tunnel over the internet
Key Features:
- Quick setup (minutes, not months)
- IPsec encryption
- Redundant tunnels for high availability
- Dynamic routing with BGP
Use Cases:
- Quick hybrid cloud setup
- Backup connectivity for Direct Connect
- Low to medium bandwidth requirements
- Cost-sensitive scenarios
- Temporary connectivity needs
Pricing Model:
- VPN connection hour fees (~$0.05/hour)
- Data transfer out fees (standard internet rates)
- Lower fixed costs than Direct Connect
Hybrid Network Architecture Patterns
Pattern 1: Site-to-Site VPN Architecture
// lib/hybrid-vpn-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
export class HybridVPNStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPC for AWS workloads
const vpc = new ec2.Vpc(this, 'HybridVPC', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
maxAzs: 2,
natGateways: 1,
subnetConfiguration: [
{
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
cidrMask: 24,
},
{
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
cidrMask: 24,
},
],
});
// Customer Gateway (on-premise VPN device)
const customerGateway = new ec2.CfnCustomerGateway(
this,
'CustomerGateway',
{
bgpAsn: 65000, // Your BGP ASN
ipAddress: '203.0.113.12', // Public IP of on-premise VPN device
type: 'ipsec.1',
tags: [
{
key: 'Name',
value: 'OnPremise-VPN-Gateway',
},
],
}
);
// Virtual Private Gateway (AWS side)
const vpnGateway = new ec2.CfnVPNGateway(this, 'VPNGateway', {
type: 'ipsec.1',
amazonSideAsn: 64512, // AWS BGP ASN
tags: [
{
key: 'Name',
value: 'AWS-VPN-Gateway',
},
],
});
// Attach VPN Gateway to VPC
const vpcGatewayAttachment = new ec2.CfnVPCGatewayAttachment(
this,
'VPCGatewayAttachment',
{
vpcId: vpc.vpcId,
vpnGatewayId: vpnGateway.ref,
}
);
// Site-to-Site VPN Connection
const vpnConnection = new ec2.CfnVPNConnection(this, 'VPNConnection', {
type: 'ipsec.1',
staticRoutesOnly: false, // Use BGP for dynamic routing
customerGatewayId: customerGateway.ref,
vpnGatewayId: vpnGateway.ref,
vpnTunnelOptionsSpecifications: [
{
// Tunnel 1 configuration
preSharedKey: 'tunnel1-pre-shared-key-replace-me', // Use Secrets Manager in production
tunnelInsideCidr: '169.254.10.0/30',
},
{
// Tunnel 2 configuration (redundancy)
preSharedKey: 'tunnel2-pre-shared-key-replace-me',
tunnelInsideCidr: '169.254.11.0/30',
},
],
tags: [
{
key: 'Name',
value: 'Hybrid-VPN-Connection',
},
],
});
// Enable route propagation for VPN
vpc.privateSubnets.forEach((subnet, index) => {
new ec2.CfnVPNGatewayRoutePropagation(
this,
`RoutePropagation${index}`,
{
routeTableIds: [subnet.routeTable.routeTableId],
vpnGatewayId: vpnGateway.ref,
}
);
});
// CloudWatch alarm for VPN tunnel status
const tunnelStateAlarm = new cdk.aws_cloudwatch.Alarm(
this,
'VPNTunnelStateAlarm',
{
alarmName: 'vpn-tunnel-down',
metric: new cdk.aws_cloudwatch.Metric({
namespace: 'AWS/VPN',
metricName: 'TunnelState',
dimensionsMap: {
VpnId: vpnConnection.ref,
},
statistic: 'Maximum',
period: cdk.Duration.minutes(1),
}),
threshold: 0, // 0 = down, 1 = up
evaluationPeriods: 2,
comparisonOperator:
cdk.aws_cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
treatMissingData: cdk.aws_cloudwatch.TreatMissingData.BREACHING,
}
);
// Outputs
new cdk.CfnOutput(this, 'VPCId', {
value: vpc.vpcId,
description: 'VPC ID for hybrid workloads',
});
new cdk.CfnOutput(this, 'VPNConnectionId', {
value: vpnConnection.ref,
description: 'VPN Connection ID',
});
new cdk.CfnOutput(this, 'VPNGatewayId', {
value: vpnGateway.ref,
description: 'Virtual Private Gateway ID',
});
}
}
Pattern 2: AWS Direct Connect Architecture
# terraform/direct_connect.tf
# Terraform configuration for AWS Direct Connect
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}
# VPC for AWS workloads
resource "aws_vpc" "hybrid_vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "Hybrid-Direct-Connect-VPC"
}
}
# Private subnets
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.hybrid_vpc.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "Private-Subnet-${count.index + 1}"
}
}
# Virtual Private Gateway for Direct Connect
resource "aws_vpn_gateway" "vgw" {
vpc_id = aws_vpc.hybrid_vpc.id
amazon_side_asn = 64512
tags = {
Name = "Direct-Connect-VGW"
}
}
# Direct Connect Gateway (for multi-VPC connectivity)
resource "aws_dx_gateway" "dx_gateway" {
name = "hybrid-dx-gateway"
amazon_side_asn = 64512
}
# Associate Direct Connect Gateway with Virtual Private Gateway
resource "aws_dx_gateway_association" "vgw_association" {
dx_gateway_id = aws_dx_gateway.dx_gateway.id
associated_gateway_id = aws_vpn_gateway.vgw.id
allowed_prefixes = [
"10.0.0.0/16", # VPC CIDR
]
}
# Direct Connect Connection (typically ordered through AWS Console/API)
# This is a placeholder - actual connection is provisioned separately
resource "aws_dx_connection" "on_premise" {
name = "OnPremise-DX-Connection"
bandwidth = "1Gbps" # Or "10Gbps"
location = "EqFR2" # Frankfurt Equinix location code
tags = {
Name = "OnPremise-Direct-Connect"
Environment = "Production"
}
}
# Private Virtual Interface (VIF) for private connectivity
resource "aws_dx_private_virtual_interface" "private_vif" {
connection_id = aws_dx_connection.on_premise.id
name = "Private-VIF-to-VPC"
vlan = 100
address_family = "ipv4"
bgp_asn = 65000 # Customer BGP ASN
# BGP peering configuration
amazon_address = "169.254.10.1/30"
customer_address = "169.254.10.2/30"
bgp_auth_key = "SecureBGPKey123" # Use Secrets Manager in production
dx_gateway_id = aws_dx_gateway.dx_gateway.id
tags = {
Name = "Private-VIF-Production"
}
}
# CloudWatch monitoring for Direct Connect
resource "aws_cloudwatch_metric_alarm" "dx_connection_state" {
alarm_name = "direct-connect-connection-down"
comparison_operator = "LessThanThreshold"
evaluation_periods = 2
metric_name = "ConnectionState"
namespace = "AWS/DX"
period = 60
statistic = "Minimum"
threshold = 1 # 1 = up, 0 = down
alarm_description = "Direct Connect connection is down"
treat_missing_data = "breaching"
dimensions = {
ConnectionId = aws_dx_connection.on_premise.id
}
}
resource "aws_cloudwatch_metric_alarm" "dx_connection_bps_egress" {
alarm_name = "direct-connect-high-egress"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "ConnectionBpsEgress"
namespace = "AWS/DX"
period = 300
statistic = "Average"
threshold = 800000000 # 800 Mbps (80% of 1 Gbps)
alarm_description = "Direct Connect egress bandwidth exceeding 80%"
dimensions = {
ConnectionId = aws_dx_connection.on_premise.id
}
}
# Route table for Direct Connect traffic
resource "aws_route_table" "dx_route_table" {
vpc_id = aws_vpc.hybrid_vpc.id
tags = {
Name = "Direct-Connect-Route-Table"
}
}
# Enable route propagation from VPN Gateway
resource "aws_vpn_gateway_route_propagation" "dx_routes" {
vpn_gateway_id = aws_vpn_gateway.vgw.id
route_table_id = aws_route_table.dx_route_table.id
}
# Associate route table with private subnets
resource "aws_route_table_association" "private" {
count = 2
subnet_id = aws_subnet.private[count.index].id
route_table_id = aws_route_table.dx_route_table.id
}
# Outputs
output "vpc_id" {
value = aws_vpc.hybrid_vpc.id
description = "VPC ID for hybrid workloads"
}
output "dx_connection_id" {
value = aws_dx_connection.on_premise.id
description = "Direct Connect connection ID"
}
output "dx_gateway_id" {
value = aws_dx_gateway.dx_gateway.id
description = "Direct Connect Gateway ID"
}
output "private_vif_id" {
value = aws_dx_private_virtual_interface.private_vif.id
description = "Private Virtual Interface ID"
}
Pattern 3: AWS Outposts Deployment
// lib/outposts-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
export class OutpostsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPC that spans AWS Region and Outpost
const vpc = new ec2.Vpc(this, 'OutpostsVPC', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
maxAzs: 1,
natGateways: 0,
subnetConfiguration: [
{
name: 'Outpost-Subnet',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
cidrMask: 24,
},
],
});
// Note: Actual Outpost subnet creation requires Outpost ID
// This is typically done via Console after Outpost is installed
/*
const outpostSubnet = new ec2.CfnSubnet(this, 'OutpostSubnet', {
vpcId: vpc.vpcId,
cidrBlock: '10.0.100.0/24',
outpostArn: 'arn:aws:outposts:eu-central-1:123456789012:outpost/op-1234567890abcdef0',
availabilityZone: 'eu-central-1a',
});
*/
// IAM role for Outposts instances
const outpostsRole = new iam.Role(this, 'OutpostsInstanceRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
description: 'Role for EC2 instances on Outposts',
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
],
});
// Security group for Outposts workloads
const outpostsSG = new ec2.SecurityGroup(this, 'OutpostsSecurityGroup', {
vpc,
description: 'Security group for Outposts instances',
allowAllOutbound: true,
});
// Allow connectivity from on-premise network
outpostsSG.addIngressRule(
ec2.Peer.ipv4('192.168.0.0/16'), // On-premise CIDR
ec2.Port.allTraffic(),
'Allow all traffic from on-premise'
);
// Example: EC2 instance on Outpost (requires Outpost subnet)
/*
const outpostInstance = new ec2.Instance(this, 'OutpostInstance', {
vpc,
vpcSubnets: {
subnets: [outpostSubnet],
},
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.M5,
ec2.InstanceSize.XLARGE
),
machineImage: ec2.MachineImage.latestAmazonLinux2(),
securityGroup: outpostsSG,
role: outpostsRole,
});
*/
// Local Gateway Route Table (for on-premise connectivity)
/*
const lgwRouteTable = new ec2.CfnLocalGatewayRouteTable(
this,
'LocalGatewayRouteTable',
{
localGatewayId: 'lgw-1234567890abcdef0', // From Outpost
mode: 'direct-vpc-routing',
}
);
*/
// Outputs
new cdk.CfnOutput(this, 'VPCId', {
value: vpc.vpcId,
description: 'VPC ID spanning Region and Outpost',
});
new cdk.CfnOutput(this, 'OutpostsRoleArn', {
value: outpostsRole.roleArn,
description: 'IAM role for Outposts instances',
});
}
}
When to Choose Hybrid Cloud
Hybrid Makes Sense When:
-
Regulatory Requirements
- Data residency mandates (e.g., financial, healthcare)
- Specific compliance frameworks requiring on-premise
- Government/military security requirements
-
Technical Constraints
- Ultra-low latency requirements (< 5ms)
- Legacy systems incompatible with cloud
- Specialized hardware dependencies
- Existing significant on-premise investment
-
Gradual Migration
- Phased cloud adoption strategy
- Learning cloud technologies incrementally
- Risk mitigation through staged migration
- Maintaining operational continuity
-
Data Gravity
- Large datasets difficult to move
- Continuous data generation on-premise
- Edge computing requirements
- IoT device connectivity
Full Cloud Makes More Sense When:
-
Cloud-Native Benefits Needed
- Global scalability requirements
- Elastic workload patterns
- Innovation and agility priorities
- Minimal legacy dependencies
-
Cost Optimization
- Pay-per-use pricing advantageous
- No capital expense constraints
- Operational efficiency focus
- Small IT operations team
-
No Compliance Blockers
- No data residency restrictions
- Cloud-compliant regulatory framework
- Acceptable shared responsibility model
Cost Comparison: Direct Connect vs. VPN
Direct Connect Costs (1 Gbps, eu-central-1)
Monthly Costs:
Port Hours: 1 Gbps × 730 hours × $0.30/hour = $219/month
Data Transfer Out: 10 TB × $0.02/GB = $200/month
Total: ~$419/month (plus cross-connect fees)
Annual Cost: ~$5,000
Characteristics:
- Predictable, consistent performance
- Lower data transfer costs at scale
- Higher fixed costs
- Suitable for: >5 TB/month transfer, latency-sensitive workloads
Site-to-Site VPN Costs
Monthly Costs:
VPN Connection: 730 hours × $0.05/hour = $36.50/month
Data Transfer Out: 10 TB × $0.09/GB = $900/month
Total: ~$936.50/month
Annual Cost: ~$11,200
Characteristics:
- Lower fixed costs
- Higher variable costs at scale
- Internet-dependent performance
- Suitable for: <5 TB/month transfer, backup connectivity
Break-Even Analysis
Direct Connect becomes cost-effective when:
- Monthly data transfer > 5-10 TB
- Latency consistency critical
- Long-term hybrid cloud strategy (>1 year)
VPN remains cost-effective when:
- Monthly data transfer < 5 TB
- Temporary connectivity needed
- Budget constraints significant
- Can tolerate internet variability
Best Practices
1. Network Design
- Design for redundancy (multiple connections/tunnels)
- Implement proper CIDR planning to avoid overlaps
- Use BGP for dynamic routing where possible
- Monitor bandwidth and latency continuously
- Plan for growth in bandwidth requirements
2. Security
- Encrypt all data in transit (IPsec for VPN, MACSec for Direct Connect)
- Implement least-privilege access controls
- Use AWS PrivateLink for service connectivity
- Regular security audits of hybrid connectivity
- Implement network segmentation
3. Performance Optimization
- Place workloads close to data sources (consider Outposts)
- Use AWS Global Accelerator for consistent performance
- Implement caching strategies (CloudFront, ElastiCache)
- Monitor latency and optimize data transfer patterns
- Consider Direct Connect for high-bandwidth workloads
4. Cost Management
- Right-size Direct Connect bandwidth
- Use VPN as backup, not primary for large data
- Implement data transfer optimization
- Regular cost analysis and optimization
- Consider AWS Cost Anomaly Detection
5. Operational Excellence
- Automate infrastructure deployment (IaC)
- Implement comprehensive monitoring
- Document network topology thoroughly
- Regular DR testing for hybrid failover
- Maintain runbooks for common scenarios
Conclusion
Hybrid cloud strategies provide flexibility for organizations with specific regulatory, technical, or operational requirements. AWS offers comprehensive services from Outposts for on-premise AWS infrastructure to Direct Connect and Site-to-Site VPN for network connectivity. Choosing the right approach depends on latency requirements, data volumes, compliance needs, and budget constraints.
Key Takeaways:
- Evaluate hybrid vs. full cloud based on specific requirements
- Direct Connect for high-bandwidth, latency-sensitive workloads
- Site-to-Site VPN for quick setup and lower data volumes
- AWS Outposts for on-premise AWS infrastructure
- Design for redundancy and monitor continuously
- Regular cost optimization and performance tuning
Ready to design your hybrid cloud architecture? Forrict specializes in hybrid cloud implementations, helping Dutch organizations seamlessly integrate on-premise and AWS infrastructure.
Resources
- AWS Outposts
- AWS Direct Connect
- AWS Site-to-Site VPN
- AWS Hybrid Cloud Whitepaper
- AWS Direct Connect Pricing
Forrict Team
AWS expert and consultant at Forrict, specializing in cloud architecture and AWS best practices for Dutch businesses.