AWS Outposts: Run AWS Infrastructure On-Premises (2026)
Moving every workload to the cloud is the dream — but reality is messier. Manufacturing plants need sub-millisecond latency for PLC systems. Banks in the EU must guarantee that patient or financial data never leaves a specific country. Hospital imaging systems process 40 GB DICOM scans that can't traverse a 100 ms WAN link before the radiologist needs to act. These aren't edge cases — they're the mainstream enterprise reality that AWS Outposts was built to address.
AWS Outposts brings the actual AWS hardware — the same Nitro hypervisor, the same APIs, the same control plane — physically into your data center or co-location facility. You manage EC2, EBS, S3, EKS, RDS, and more using the exact same CLI commands, CloudFormation templates, and Terraform modules you use in the cloud. The only difference is the compute runs inside your four walls, not Amazon's.
This guide covers everything: form factors, network prerequisites, supported services with their limitations, real CLI commands, Terraform HCL, Kubernetes YAML, monitoring strategy, and a frank cost analysis to help you decide whether Outposts is the right tool for your specific problem — or whether Local Zones, Wavelength, or the Snow family would serve you better.
Table of Contents
- Outposts vs Local Zones vs Wavelength vs Snow Family
- Form Factors and Pricing Model
- Network Prerequisites: Service Link and Local Gateway
- Supported Services and Limitations
- EC2 on Outposts: Placement, Reservations, and Launch
- EKS on Outposts: Local Control Plane and Node Groups
- S3 on Outposts: Access Points and Data Residency
- RDS on Outposts: Supported Engines and Multi-AZ
- Monitoring, Health Checks, and Disconnected Mode
- Cost Model, Business Cases, and ROI Analysis
Outposts vs Local Zones vs Wavelength vs Snow Family
AWS offers four distinct solutions for workloads that can't or shouldn't run in a standard region. Understanding which tool to reach for requires mapping your technical constraints — latency, data sovereignty, connectivity, and operational model — against each offering's capabilities.
| Dimension | Outposts | Local Zones | Wavelength | Snow Family |
|---|---|---|---|---|
| Hardware location | Your data center / colo | AWS-managed metro facility | Telco 5G network edge | Portable — ships to you |
| Who manages hardware | AWS (you rack it, AWS owns it) | AWS | AWS + Telco | You (physically) |
| Latency target | <1 ms (on-premises LAN) | Single-digit ms (metro) | <10 ms (5G RAN) | Offline / air-gapped |
| Data sovereignty | Full — data stays in your facility | No — AWS facility | No — telco facility | Full — fully disconnected |
| Internet required | Yes (service link to parent region) | Yes | Yes | Optional (Snowball Edge offline) |
| Service breadth | Broad (EC2, EBS, S3, EKS, RDS, ElastiCache) | Subset of region services | EC2, ECS, EKS only | EC2, S3, Lambda (limited) |
| Best for | GDPR/HIPAA residence, ultra-low latency factory, hybrid lift-and-shift | Media production, gaming, AR/VR | Real-time 5G apps, autonomous vehicles | Disconnected/remote sites, data migration |
| Minimum commitment | 3 years (rack rental) or purchase | On-demand | On-demand | Job-based rental |
A common misconception is that Outposts is just for latency. Latency is often a secondary benefit — the primary driver for most enterprise Outposts deployments is data sovereignty. A German bank subject to BaFin regulations, a UK NHS trust processing patient records under UK GDPR, or a US defense contractor under ITAR — all of these have hard legal prohibitions on data leaving specified geographic or organizational boundaries. Outposts is the only AWS service that gives you compute that is physically isolated inside your own facility while still running native AWS APIs.
Snow Family (Snowball Edge, Snowcone, Snowmobile) serves a different use case: truly disconnected or intermittently connected environments. A research vessel at sea, a pipeline monitoring station in the Arctic, or a military forward operating base — Snow devices operate without any AWS connectivity, sync when a connection is available. Outposts requires a persistent (or at least recoverable) link to the parent region via its service link.
Form Factors and Pricing Model
AWS Outposts is not a single product — it is a family of hardware configurations designed to fit different data center sizes, power budgets, and capacity requirements. As of 2026, three physical form factors are available.
Outposts Rack (42U)
The flagship offering. A full 42U rack shipped by AWS and installed by AWS field engineers. The rack is AWS-owned property sitting in your data center. It includes Nitro-based servers, EBS storage units, and networking gear — all pre-configured and cabled. You provide the data center floor space, power (typically 15 kW per rack), cooling, and physical security. AWS provides the hardware maintenance: if a drive fails, an AWS engineer comes on-site to replace it under a defined SLA.
Rack configurations range from small (starting at a handful of EC2 instance capacity) to large (hundreds of vCPUs, terabytes of RAM, and petabytes of EBS). AWS publishes specific rack configurations like the OR-XLARGE with M5, C5, R5, G4dn, and I3en instance types. You choose the configuration at ordering time and can order multiple racks for larger footprints.
Outposts Servers (1U and 2U)
Launched in 2021 and significantly expanded since, Outposts Servers are individual rack-unit servers — not a full rack. A 1U server fits in a standard 19-inch rack you already own. A 2U server adds GPU capacity (G4dn). This makes Outposts accessible for retail stores, branch offices, and smaller facilities that cannot accommodate a full 42U rack delivery and installation.
Outposts Servers support a subset of the full rack service catalog: EC2 (C6g, M6g, R6g Graviton2 instances), ECS, EKS, and local storage — but not EBS volumes, RDS, ElastiCache, or S3 on Outposts. If your branch office just needs containerized workloads with local compute and EKS, a 2U server at $10,000–$25,000/year (estimated, varies by config) is dramatically more cost-effective than a full rack.
Pricing Model
Outposts pricing is fundamentally different from standard AWS on-demand pricing. You pay for the underlying hardware capacity, not per-hour instance usage. The model has two options:
- Rack/Server rental: AWS retains ownership, you pay a 3-year term commitment (monthly or upfront). You can return the hardware at end of term. No capital expenditure — it's OpEx.
- Rack purchase: Available in some configurations. You buy the hardware outright (CapEx). AWS still manages it remotely and provides maintenance. Less common but preferred by organizations with strict CapEx vs OpEx accounting rules.
An example pricing reference (2026, us-east-1 parent region): an OR-XLARGE rack with M5, C5, and R5 instances runs approximately $180,000–$350,000 per year on a 3-year no-upfront term. Sounds expensive until you compare it to the TCO of equivalent on-premises servers (hardware + power + cooling + maintenance staff + software licenses) over the same period, plus the benefit of identical AWS APIs and zero operational lift for hardware management.
# Check available Outposts configurations in your account
aws outposts list-outposts --query 'Outposts[*].{ID:OutpostId,Name:Name,Site:Site.SiteId,Status:LifeCycleStatus}'
# List Outpost sites
aws outposts list-sites
# Get detailed Outpost info including available instance types
aws outposts get-outpost --outpost-id op-xxxxxxxxxxxxxxxxx
# List Outpost instance types
aws outposts get-outpost-instance-types --outpost-id op-xxxxxxxxxxxxxxxxx
Network Prerequisites: Service Link and Local Gateway
Before a single EC2 instance can run on Outposts, your network must satisfy two critical connectivity requirements: the service link (connectivity from Outposts to the parent AWS region) and, for local routing, the local gateway (LGW). Getting these wrong is the most common reason Outposts deployments stall.
Service Link
The service link is an encrypted tunnel — built on top of your network connectivity — that carries control plane traffic between the Outpost hardware and the parent AWS region. Every API call you make to an Outpost (describe instances, create EBS volume, etc.) flows through the service link. Control plane operations require this link to be healthy; if it goes down, your instances keep running but you lose the ability to make API changes until connectivity restores.
The service link uses BGP-based routing and requires either AWS Direct Connect or a Site-to-Site VPN as the underlying transport. Direct Connect is strongly recommended for production Outposts — the latency and bandwidth consistency directly affect API responsiveness and EBS performance. A dedicated Direct Connect connection of at least 1 Gbps is the standard recommendation for a full rack.
# Check service link status
aws outposts get-outpost --outpost-id op-xxxxxxxxxxxxxxxxx \
--query 'Outpost.{ID:OutpostId,Status:LifeCycleStatus,ConnectivityStatus:ConnectionStatus}'
# The service link health is also visible in the Outposts console
# under "Outpost configuration" > "Connectivity status"
Local Gateway (LGW)
The local gateway is an Outposts-specific construct that enables traffic from EC2 instances on the Outpost to reach your on-premises network directly — bypassing the parent region entirely. Without LGW, all traffic from Outpost instances routes through the parent region VPC, adding latency and data transfer costs. With LGW, an Outpost instance can talk directly to a database server 10 meters away on the LAN with sub-millisecond latency.
The LGW is automatically created by AWS when the Outpost is provisioned. You configure it by creating route table entries and associating the LGW with your Outpost subnet's route table.
# List local gateways in your account
aws ec2 describe-local-gateways
# Associate LGW route table with your Outpost subnet
aws ec2 create-route \
--route-table-id rtb-xxxxxxxxxxxxxxxxx \
--destination-cidr-block 192.168.0.0/16 \
--local-gateway-id lgw-xxxxxxxxxxxxxxxxx
# Describe local gateway route tables
aws ec2 describe-local-gateway-route-tables
# Create a route to on-premises via LGW
aws ec2 search-local-gateway-routes \
--local-gateway-route-table-id lgw-rtb-xxxxxxxxxxxxxxxxx \
--filters Name=state,Values=active
Your Data Center
┌─────────────────────────────────────────────────────┐
│ ┌──────────────────────────────────────────────┐ │
│ │ AWS Outpost Rack │ │
│ │ ┌──────────┐ ┌──────────┐ ┌───────────┐ │ │
│ │ │ EC2/EBS │ │ EKS │ │RDS/Cache │ │ │
│ │ └────┬─────┘ └────┬─────┘ └─────┬─────┘ │ │
│ │ │ │ │ │ │
│ │ ┌────▼──────────────▼──────────────▼──────┐ │ │
│ │ │ Outpost VPC Subnet │ │ │
│ │ └──────────────┬───────────────────────────┘ │ │
│ └─────────────────┼──────────────────────────────┘ │
│ │ │
│ ┌─────────────────▼──────────┐ │
│ │ Local Gateway (LGW) │ │
│ │ (direct on-prem routing) │ │
│ └────────────────────────────┘ │
│ │ │
│ ┌───────────▼─────────────┐ │
│ │ On-premises LAN/WAN │ │
│ │ 192.168.0.0/16 │ │
│ └───────────┬─────────────┘ │
└──────────────┼──────────────────────────────────────┘
│
Direct Connect / VPN
│
┌──────────▼────────────┐
│ AWS Parent Region │
│ (Service Link) │
│ VPC, S3, IAM, etc. │
└───────────────────────┘
You must also configure the Outpost subnet within your VPC. An Outpost subnet is a standard VPC subnet with the additional attribute that it is associated with a specific Outpost ID. Resources launched into this subnet are physically placed on the Outpost hardware.
# Create a subnet associated with your Outpost
aws ec2 create-subnet \
--vpc-id vpc-xxxxxxxxxxxxxxxxx \
--cidr-block 10.0.10.0/24 \
--availability-zone us-east-1a \
--outpost-arn arn:aws:outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx
# Verify subnet is Outpost-associated
aws ec2 describe-subnets \
--subnet-ids subnet-xxxxxxxxxxxxxxxxx \
--query 'Subnets[0].{AZ:AvailabilityZone,OutpostArn:OutpostArn,CIDR:CidrBlock}'
Supported Services and Limitations
Not every AWS service runs on Outposts — the subset available is deliberately chosen to cover the most common on-premises use cases while keeping the hardware and software stack manageable. Understanding the current service catalog and its limitations prevents nasty surprises mid-migration.
| Service | Available on Outposts Rack | Available on Outposts Servers | Key Limitations |
|---|---|---|---|
| EC2 | Yes | Yes (Graviton2 only) | Not all instance families; no Spot instances |
| EBS | Yes (gp2, gp3, io1) | No | Snapshots stored in parent region S3 |
| S3 on Outposts | Yes | No | Separate from S3; requires S3 on Outposts bucket type |
| ECS | Yes | Yes | Fargate not supported — EC2 launch type only |
| EKS | Yes | Yes | Self-managed node groups; Fargate profiles not supported |
| RDS | MySQL, PostgreSQL only | No | Aurora, Oracle, SQL Server not supported on Outposts |
| ElastiCache | Redis, Memcached | No | Single-AZ only (no cross-AZ replication from Outpost) |
| EMR | Yes | No | Subset of instance types; HDFS only (no S3 as primary) |
| App Mesh | Yes | No | Control plane in parent region |
| ALB / NLB | Yes (Application LB) | No | NLB not supported; ALB limited features |
| Lambda | No | No | Not supported; use ECS/EKS for serverless-style |
| DynamoDB | No | No | Not supported; use RDS or ElastiCache on Outpost |
EC2 on Outposts: Placement, Reservations, and Launch
Running EC2 on Outposts is operationally identical to standard EC2 — same API, same CLI, same CloudFormation. The key differences are in placement (you must target the Outpost subnet), instance type availability (limited to what's in your Outpost configuration), and capacity reservations (Outposts uses a different reservation model).
Instance Placement
To place an instance on the Outpost, simply launch it into the Outpost subnet. AWS's scheduler automatically places it on the physical Outpost hardware. You cannot specify a particular server within the rack — AWS manages physical placement. For workloads requiring isolation between tenants, use dedicated host placement.
# Launch EC2 instance on Outposts — target the Outpost subnet
aws ec2 run-instances \
--image-id ami-xxxxxxxxxxxxxxxxx \
--instance-type m5.xlarge \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--key-name my-key-pair \
--security-group-ids sg-xxxxxxxxxxxxxxxxx \
--count 1 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=outpost-app-server}]'
# Verify instance is running on Outpost
aws ec2 describe-instances \
--instance-ids i-xxxxxxxxxxxxxxxxx \
--query 'Reservations[0].Instances[0].{State:State.Name,AZ:Placement.AvailabilityZone,Outpost:OutpostArn}'
Capacity Reservations on Outposts
Standard EC2 capacity reservations work on Outposts but with a twist: on an Outpost, all capacity is effectively reserved at the time of Outpost provisioning. The Outpost rack's total compute is not shared with other AWS customers — it's dedicated to your account. This means capacity reservations are primarily useful for ensuring specific teams or workloads always have access to a portion of the Outpost's capacity without other teams in the same account consuming it.
# Create a capacity reservation on an Outpost
aws ec2 create-capacity-reservation \
--instance-type m5.xlarge \
--instance-platform Linux/UNIX \
--availability-zone us-east-1a \
--instance-count 10 \
--outpost-arn arn:aws:outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx \
--end-date-type unlimited
# Launch instance into the capacity reservation
aws ec2 run-instances \
--image-id ami-xxxxxxxxxxxxxxxxx \
--instance-type m5.xlarge \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--capacity-reservation-specification \
CapacityReservationTarget={CapacityReservationId=cr-xxxxxxxxxxxxxxxxx}
AMI Constraints
Most standard AWS AMIs work on Outposts without modification — the underlying Nitro hypervisor is identical. However, AMIs must be available in the parent region's AZ corresponding to your Outpost. Custom AMIs built on hardware-specific features (specific CPU instruction sets not present in the Outpost instance type) may need adjustment. Always test AMIs on a running Outpost instance before committing to production deployment.
resource "aws_subnet" "outpost_subnet" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.10.0/24"
availability_zone = "us-east-1a"
outpost_arn = "arn:aws:outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx"
tags = {
Name = "outpost-primary-subnet"
}
}
resource "aws_instance" "outpost_app" {
ami = data.aws_ami.amazon_linux.id
instance_type = "m5.xlarge"
subnet_id = aws_subnet.outpost_subnet.id
key_name = aws_key_pair.app.key_name
root_block_device {
volume_type = "gp2"
volume_size = 50
}
tags = {
Name = "outpost-app-server"
Environment = "production"
DataClass = "confidential"
}
}
EKS on Outposts: Local Control Plane and Node Groups
EKS on Outposts supports two operational modes: connected clusters (control plane in the parent region, worker nodes on Outpost) and local clusters (both control plane and worker nodes physically on the Outpost). The local cluster mode, introduced in 2022, is the game-changer for latency-sensitive and sovereignty-constrained Kubernetes workloads.
Local Clusters (Fully On-Premises Control Plane)
In local cluster mode, AWS runs the Kubernetes control plane — etcd, API server, controller manager, scheduler — on dedicated control plane instances physically located on your Outpost rack. You do not manage these instances; AWS manages them as part of the managed EKS service. However, they are running in your facility.
This means that even if the service link to the parent region is interrupted, the Kubernetes control plane continues to operate. Existing pods keep running, new pods can be scheduled, and Kubernetes API calls succeed — all locally. This "disconnected mode resilience" makes local clusters the right choice for factory automation and industrial IoT where internet connectivity may be intermittent.
# Create an EKS local cluster on Outposts
aws eks create-cluster \
--name outpost-local-cluster \
--role-arn arn:aws:iam::123456789012:role/eks-cluster-role \
--resources-vpc-config \
subnetIds=subnet-xxxxxxxxxxxxxxxxx,\
securityGroupIds=sg-xxxxxxxxxxxxxxxxx \
--outpost-config \
outpostArns=arn:aws:outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx,\
controlPlaneInstanceType=m5.xlarge \
--kubernetes-version 1.29
# Check cluster status
aws eks describe-cluster \
--name outpost-local-cluster \
--query 'cluster.{Status:status,OutpostConfig:outpostConfig}'
# Update kubeconfig
aws eks update-kubeconfig \
--name outpost-local-cluster \
--region us-east-1
Self-Managed Node Groups
Managed node groups are not supported for Outpost clusters — you use self-managed node groups instead. This means you launch EC2 instances manually (or via Launch Templates / Auto Scaling Groups), configure them with the EKS bootstrap script, and register them with the cluster.
# eks-outpost-nodegroup.yaml — Auto Scaling Group for Outpost worker nodes
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789012:role/eks-node-role
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
# Launch self-managed worker node into Outpost subnet
aws ec2 run-instances \
--image-id ami-eks-optimized-xxxxxxxxx \
--instance-type m5.xlarge \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--iam-instance-profile Name=eks-node-instance-profile \
--security-group-ids sg-xxxxxxxxxxxxxxxxx \
--user-data file://eks-bootstrap.sh \
--count 3 \
--tag-specifications \
'ResourceType=instance,Tags=[{Key=kubernetes.io/cluster/outpost-local-cluster,Value=owned}]'
#!/bin/bash
# eks-bootstrap.sh — user data script for Outpost worker nodes
/etc/eks/bootstrap.sh outpost-local-cluster \
--b64-cluster-ca $CLUSTER_CA \
--apiserver-endpoint $CLUSTER_ENDPOINT \
--container-runtime containerd \
--kubelet-extra-args '--node-labels=topology.kubernetes.io/zone=us-east-1a-local'
Networking Considerations for EKS on Outposts
The VPC CNI (aws-node DaemonSet) works on Outposts nodes using the same pod IP allocation from VPC CIDR ranges. CoreDNS runs locally on the Outpost for in-cluster DNS resolution. For local clusters, the Kubernetes API endpoint resolves to an IP on the Outpost — DNS entries are managed by EKS automatically. Ingress controllers (AWS Load Balancer Controller for ALB) work with the Outpost-local ALB if Application Load Balancer is available in your Outpost configuration.
# Example deployment targeting Outpost nodes via node affinity
apiVersion: apps/v1
kind: Deployment
metadata:
name: factory-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: factory-app
template:
metadata:
labels:
app: factory-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a-local # Outpost AZ label
containers:
- name: factory-app
image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/factory-app:latest
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "2Gi"
S3 on Outposts: Access Points and Data Residency Compliance
S3 on Outposts is a distinct storage service from standard Amazon S3. When you create an "S3 on Outposts" bucket, the objects are physically stored on the Outpost hardware — they never leave your facility. This is categorically different from a standard S3 bucket with no replication, where data resides in AWS data centers.
S3 on Outposts uses the same S3 API (PutObject, GetObject, ListObjects) but with an access point ARN syntax rather than a bucket URL. The access point provides network-path isolation — you can create separate access points for different applications or teams, each with its own access policy.
# Step 1: Create an S3 on Outposts bucket
aws s3control create-bucket \
--bucket my-outpost-bucket \
--outpost-id op-xxxxxxxxxxxxxxxxx \
--create-bucket-configuration LocationConstraint=us-east-1
# Step 2: Create an access point for the Outpost bucket
aws s3control create-access-point \
--account-id 123456789012 \
--name outpost-app-access-point \
--bucket arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx/bucket/my-outpost-bucket \
--vpc-configuration VpcId=vpc-xxxxxxxxxxxxxxxxx
# Step 3: Get the access point ARN for use in application config
aws s3control get-access-point \
--account-id 123456789012 \
--name outpost-app-access-point \
--query 'AccessPointArn'
# Upload object using access point ARN
aws s3api put-object \
--bucket arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx/accesspoint/outpost-app-access-point \
--key patient-records/2026/record-001.json \
--body record-001.json \
--server-side-encryption aws:kms
# Download object
aws s3api get-object \
--bucket arn:aws:s3-outposts:us-east-1:123456789012:outpost/op-xxxxxxxxxxxxxxxxx/accesspoint/outpost-app-access-point \
--key patient-records/2026/record-001.json \
output.json
# List objects in the bucket
aws s3control list-regional-buckets \
--account-id 123456789012 \
--outpost-id op-xxxxxxxxxxxxxxxxx
S3 on Outposts has meaningful capacity limits compared to standard S3. Each Outpost has a fixed storage capacity (determined at rack configuration time — typically 48 TB to 96 TB of usable S3 storage). You must monitor storage utilization proactively; there is no automatic elastic expansion like standard S3. CloudWatch provides metrics for storage utilization on Outposts S3.
# Check S3 on Outposts storage utilization
aws cloudwatch get-metric-statistics \
--namespace AWS/S3Outposts \
--metric-name BytesUsed \
--dimensions Name=OutpostId,Value=op-xxxxxxxxxxxxxxxxx \
--start-time 2026-06-01T00:00:00Z \
--end-time 2026-06-09T00:00:00Z \
--period 86400 \
--statistics Average
RDS on Outposts: Supported Engines and Multi-AZ
RDS on Outposts brings managed relational databases to your on-premises environment. Instead of installing and managing MySQL or PostgreSQL yourself, AWS runs the database engine on Outpost hardware using the same RDS managed service experience: automated backups, parameter group management, minor version upgrades, and monitoring through CloudWatch.
Supported Engines
As of 2026, RDS on Outposts supports MySQL 8.0+ and PostgreSQL 13+. Microsoft SQL Server, Oracle, MariaDB, and Aurora are not supported on Outposts. Aurora specifically requires a distributed storage system that spans multiple AZs — a constraint that is fundamentally incompatible with a single physical rack.
# Create an RDS instance on Outposts (MySQL)
aws rds create-db-instance \
--db-instance-identifier outpost-mysql-prod \
--db-instance-class db.m5.xlarge \
--engine mysql \
--engine-version 8.0.35 \
--master-username admin \
--master-user-password 'SecurePassword123!' \
--db-subnet-group-name outpost-db-subnet-group \
--allocated-storage 500 \
--storage-type gp2 \
--no-multi-az \
--backup-retention-period 7 \
--preferred-backup-window "03:00-04:00" \
--tags Key=Environment,Value=production Key=DataClass,Value=confidential
# Check instance status
aws rds describe-db-instances \
--db-instance-identifier outpost-mysql-prod \
--query 'DBInstances[0].{Status:DBInstanceStatus,Endpoint:Endpoint.Address,AZ:AvailabilityZone}'
DB Subnet Group for Outposts
Before creating the RDS instance, create a DB subnet group that includes your Outpost subnet. RDS requires the subnet group to specify Outpost subnets explicitly.
# Create DB subnet group for Outpost
aws rds create-db-subnet-group \
--db-subnet-group-name outpost-db-subnet-group \
--db-subnet-group-description "Subnet group for RDS on Outposts" \
--subnet-ids subnet-xxxxxxxxxxxxxxxxx subnet-yyyyyyyyyyyyyyyyy
# Verify subnet group includes Outpost subnets
aws rds describe-db-subnet-groups \
--db-subnet-group-name outpost-db-subnet-group \
--query 'DBSubnetGroups[0].Subnets[*].{SubnetId:SubnetIdentifier,Status:SubnetStatus}'
Multi-AZ on Outposts
Multi-AZ for RDS on Outposts is supported via a standby instance in the parent region AZ — not a second Outpost rack. This means the standby replica is in AWS infrastructure, and in a failover scenario, your database endpoint points to the cloud. This protects against Outpost hardware failure but does not maintain data residency during failover. If data residency is mandatory even during failover, you must implement a custom HA architecture (e.g., two Outpost racks in separate facilities with MySQL Group Replication or PostgreSQL Patroni).
Backups to Parent Region
Automated RDS backups on Outposts are stored in the parent region S3 — not on the Outpost. This is a critical compliance consideration: your backup data crosses the boundary to AWS infrastructure. Depending on your regulatory requirements, this may be acceptable (backup encryption with customer-managed KMS keys satisfies many frameworks) or may require an exception or alternative backup strategy.
resource "aws_db_subnet_group" "outpost" {
name = "outpost-db-subnet-group"
subnet_ids = [aws_subnet.outpost_subnet.id]
tags = { Name = "Outpost DB Subnet Group" }
}
resource "aws_db_instance" "outpost_postgres" {
identifier = "outpost-postgres-prod"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.m5.large"
allocated_storage = 200
storage_type = "gp2"
db_subnet_group_name = aws_db_subnet_group.outpost.name
vpc_security_group_ids = [aws_security_group.db.id]
username = "dbadmin"
password = var.db_password
backup_retention_period = 7
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "outpost-postgres-final-snap"
tags = {
Environment = "production"
DataClass = "PHI"
Compliance = "HIPAA"
}
}
Monitoring, Health Checks, and Disconnected Mode Behaviour
Monitoring an Outpost requires understanding that metrics flow through the service link to CloudWatch in the parent region. When the service link is healthy, all standard CloudWatch metrics — EC2 CPU/network, EBS IOPS, RDS connections, EKS node status — are available with no special configuration. When the service link is degraded or down, metric delivery is buffered on the Outpost and forwarded when connectivity restores.
Outpost-Specific CloudWatch Metrics
# Check Outpost connectivity health via CloudWatch
aws cloudwatch get-metric-statistics \
--namespace AWS/Outposts \
--metric-name OutpostConnectivity \
--dimensions Name=OutpostId,Value=op-xxxxxxxxxxxxxxxxx \
--start-time 2026-06-08T00:00:00Z \
--end-time 2026-06-09T00:00:00Z \
--period 300 \
--statistics Average
# Monitor Outpost capacity utilization
aws cloudwatch get-metric-statistics \
--namespace AWS/Outposts \
--metric-name ComputeCapacityUsed \
--dimensions Name=OutpostId,Value=op-xxxxxxxxxxxxxxxxx \
--start-time 2026-06-08T00:00:00Z \
--end-time 2026-06-09T00:00:00Z \
--period 3600 \
--statistics Average,Maximum
# Create CloudWatch alarm for Outpost connectivity loss
aws cloudwatch put-metric-alarm \
--alarm-name outpost-connectivity-alarm \
--alarm-description "Alert when Outpost connectivity to parent region is lost" \
--namespace AWS/Outposts \
--metric-name OutpostConnectivity \
--dimensions Name=OutpostId,Value=op-xxxxxxxxxxxxxxxxx \
--period 300 \
--evaluation-periods 2 \
--threshold 1 \
--comparison-operator LessThanThreshold \
--statistic Average \
--alarm-actions arn:aws:sns:us-east-1:123456789012:ops-alerts \
--treat-missing-data breaching
Disconnected Mode Behaviour
The Outpost enters "disconnected mode" when the service link to the parent region is unavailable. The behaviour in disconnected mode depends on the service:
- Running EC2 instances: Continue running normally. Existing instances are unaffected.
- New EC2 instance launches: Blocked — the control plane (which validates IAM, processes API calls) is in the parent region and unreachable.
- EKS local clusters: Control plane continues operating (it's local). New pod scheduling, existing pod management, and Kubernetes API calls all work. ecr.aws image pulls fail if ECR is in the parent region.
- EKS connected clusters: Control plane is in the parent region and unreachable. Existing pods continue running (kubelet continues on nodes) but no new scheduling.
- RDS: The database continues serving connections. Automated backups are queued and forwarded when connectivity restores.
- S3 on Outposts: Local reads and writes continue. S3 replication (if configured) is queued.
- CloudWatch metrics: Buffered locally, delivered when connectivity restores. Up to 2 weeks of metrics can be buffered.
Terraform — CloudWatch Dashboard for Outpost Health
resource "aws_cloudwatch_dashboard" "outpost_health" {
dashboard_name = "outpost-health-dashboard"
dashboard_body = jsonencode({
widgets = [
{
type = "metric"
properties = {
title = "Outpost Connectivity"
metrics = [["AWS/Outposts", "OutpostConnectivity",
"OutpostId", "op-xxxxxxxxxxxxxxxxx"]]
period = 60
stat = "Average"
view = "timeSeries"
}
},
{
type = "metric"
properties = {
title = "EC2 CPU Utilization (Outpost)"
metrics = [["AWS/EC2", "CPUUtilization"]]
period = 300
stat = "Average"
view = "timeSeries"
}
}
]
})
}
Cost Model, Business Cases, and ROI Analysis
AWS Outposts has a reputation for being expensive — and for the wrong workloads, it is. But for the right workloads, the total cost of ownership (TCO) comparison against traditional on-premises infrastructure or hybrid alternatives often makes Outposts surprisingly competitive. The key is being rigorous about what you're comparing.
Traditional On-Premises TCO Components (often underestimated)
- Hardware purchase (servers, storage arrays, networking gear): typically depreciated over 3–5 years
- Data center space, power, and cooling: often $800–$2,000 per rack per month in co-location facilities
- Hardware maintenance contracts: typically 15–20% of hardware cost per year
- System administration labor: 0.5–2 FTEs per rack for patching, monitoring, troubleshooting
- Software licenses: OS, virtualization platform (VMware), database, monitoring tools
- Refresh cycle risk: hardware obsolescence, compatibility debt
Outposts TCO Components (often overstated)
- Outposts rack/server annual fee (covers hardware + AWS management)
- Your data center power and cooling (you still pay for this)
- EBS storage consumed (billed separately at Outpost rates)
- Data transfer from Outpost to parent region (outbound rates apply)
- Service charges for RDS, ElastiCache, EKS control plane
- AWS support plan (Business or Enterprise recommended)
Business Case Categories
Data Sovereignty and Compliance (strongest ROI): For organizations under GDPR, HIPAA, UK GDPR, PCI DSS, or FedRAMP, the cost of non-compliance — fines, breach liability, audit costs — dwarfs the Outposts premium. A GDPR fine can reach 4% of global annual turnover. Outposts as compliance infrastructure is a risk mitigation investment, not just an infrastructure cost.
Ultra-Low Latency Applications (strong ROI for specific industries): Manufacturing automation (PLCs, SCADA, robotics), financial trading systems (co-location at customer exchanges), and real-time medical imaging analysis all have latency requirements (sub-5 ms) that cannot be satisfied by any cloud region or even Local Zones. For these workloads, Outposts competes against high-end bare metal on-premises servers — and often wins on operational simplicity.
Hybrid Lift-and-Shift (moderate ROI): If you have legacy applications that cannot be refactored for cloud-native deployment but need to integrate with cloud services, Outposts lets you run them with AWS APIs and connectivity to S3, DynamoDB, and other cloud services without redesigning the application. The ROI is moderate — you avoid refactoring cost but pay the Outposts premium.
| Cost Factor | Traditional On-Prem | AWS Outposts | Standard Cloud Region |
|---|---|---|---|
| Hardware CapEx | High ($200K–$1M+ per rack equivalent) | $0 (OpEx rental model) | $0 |
| Annual infrastructure fee | $40K–$200K (maintenance + power) | $180K–$350K (rack rental, includes management) | Variable (on-demand) |
| IT staff for hardware | 0.5–2 FTE ($75K–$300K/yr) | ~0.1 FTE (AWS manages hardware) | ~0 FTE |
| Compliance risk cost | High (custom controls needed) | Low (AWS compliance programs) | Medium (data in AWS DCs) |
| Data sovereignty guarantee | Full | Full | None |
| API modernization | None (legacy APIs) | Full AWS API parity | Full AWS API parity |
When Outposts Is NOT the Right Answer
Be honest in your evaluation. Outposts is a poor choice if: your latency requirement is metro-scale (10–20 ms) and a Local Zone covers your geography; your workload will run on-premises for less than 3 years (minimum term commitment); your team lacks the AWS expertise to operate EKS, RDS, and VPC constructs (Outposts amplifies AWS operational complexity, it doesn't eliminate it); or your on-premises environment is in a location not served by Direct Connect (making the service link unreliable).