BGP Inside the VPC: What Amazon VPC Route Server Actually Changes
For years, keeping a self-managed NAT instance or firewall appliance highly available inside a VPC meant a health-check script rewriting route tables through the EC2 API. AWS's own case study on how ad-tech firm Magnite pushed Amazon VPC Route Server into production shows what changes once BGP, not a script, is the thing deciding your route tables.
Every network engineer who has run a self-managed NAT instance, a software firewall, or a virtual appliance inside a VPC has written some version of the same script: a health check polls the appliance, and on failure it calls the EC2 API to rewrite a route table, pointing the next hop somewhere else. It works, most of the time. It is also not routing — it is infrastructure automation pretending to be routing, with none of the negotiation, preference, or sub-second failure detection an actual routing protocol gives you for free. For most of the last decade, that gap was simply how VPC routing worked: static tables, no protocol underneath them, no exceptions.
On 21 July 2026, AWS’s Networking & Content Delivery blog published a case study on how Magnite — an ad-tech company processing more than a trillion ad requests a day — closed that gap in production using Amazon VPC Route Server to run genuine BGP sessions inside their VPCs. Not BGP as a Direct Connect or Transit Gateway edge protocol, which is where AWS networking BGP has always lived. BGP deciding subnet route tables — the thing your workloads actually route against, this time with a routing protocol speaking for it instead of a cron job guessing.
The problem: static tables with a script bolted on
Route tables in a VPC have never been dynamic on their own. If your NAT
instance dies, nothing reroutes traffic unless something outside the
data plane notices and acts. For most teams that “something” is
home-grown: a Lambda function or a daemon on a companion instance,
polling a health endpoint every few seconds and calling
ReplaceRoute when it decides the primary is dead. It’s a workable
pattern, and thousands of production VPCs run it today. It is also
slow and blind in ways a routing protocol isn’t. A poll-based health
check can’t distinguish “degraded but still forwarding some traffic”
from “dead” the way BGP withdrawal semantics can. It has no concept of
preference — you can’t tell it “prefer the AZ-local instance, but only
because it’s closer, not because the other one is unhealthy.” And its
failure-detection floor is however often you’re willing to poll and how
many failed checks you require before acting, typically tens of
seconds, not the sub-second convergence BFD gives a real BGP session.
The alternative teams reached for before Route Server existed was worse: stand up a software router (BIRD, Quagga, a vendor appliance) on an EC2 instance, wrap it in a GRE or IPsec overlay, and run BGP across that overlay to get something resembling dynamic routing. That solves nothing structural, because there was no AWS-side BGP speaker inside the VPC to peer with — you were running a real routing protocol into a tunnel that terminated on another instance you also had to keep alive, adding encapsulation overhead and a second pet to operate rather than removing the original problem.
The challenge: Transit Gateway doesn’t reach inside a VPC’s own subnets
The obvious objection is that AWS already has a BGP-native routing product: Transit Gateway. It isn’t the same gap. Transit Gateway, and Cloud WAN above it, solve routing between VPCs and on-premises networks — a hub, with BGP or static routes describing what each spoke can reach. Neither one gives you a BGP speaker living inside a single VPC’s own subnet route tables, deciding in real time which of two software appliances in that same VPC should be the next hop right now. That’s a narrower, more mundane problem than “how do regions talk to each other,” and it went unsolved for years because appliance high availability within a VPC is unglamorous compared to cross-region connectivity — until it’s the thing paging you at 3am.
The solution: a managed BGP control plane, scoped to one VPC
Amazon VPC Route Server reached general availability on 1 April 2025, initially in six regions, and by 14 January 2026 had expanded to thirty. Mechanically, according to AWS’s own documentation, it has three parts. A route server is the logical BGP control plane for a VPC. A route server endpoint is an AWS-managed component that lives in one of your subnets and terminates BGP sessions. A route server peer is the actual BGP session between that endpoint and a device you run — typically an EC2 instance running a NAT gateway replacement, a firewall, or a router.
Your instance advertises routes over standard BGP, using ordinary
attributes: AWS’s own worked example uses the MED attribute so that two
devices both advertising 192.0.0.0/24 can express which one should be
preferred, with route server installing the preferred device’s ENI as
the next hop and automatically flipping to the other device the moment
BFD (Bidirectional Forwarding Detection) reports the preferred one down.
Route server builds a Routing Information Base from everything it
hears, computes a Forwarding Information Base of best paths from that
RIB, and pushes the FIB into whichever subnet, VPC, or internet gateway
route tables you’ve associated — on every BGP update, not on a polling
interval.
It’s a real control plane, not an unlimited one. AWS’s published VPC quotas cap a VPC at five route servers by default, each route server at ten endpoints, and — the two limits that aren’t adjustable at all — one hundred routes accepted per BGP peer and one hundred routes total in a route server’s FIB. Two endpoints per subnet is the maximum for a given route server, there purely for endpoint-level redundancy. Those aren’t edge cases; Magnite’s own write-up lists “plan around Amazon VPC Route Server quotas early” as the first lesson they’d pass on, because the hundred-route ceiling shapes the topology sooner than most teams expect — advertise a default route rather than dozens of specific prefixes if you’re bumping into it.
Magnite’s production use of this splits into two patterns. The first,
which they call MagNET, replaces a chunk of their NAT Gateway and VPC
Interface Endpoint footprint with TNSR router instances running in each
Availability Zone. Each instance advertises 0.0.0.0/0 over BGP, using
AS-path prepending — deliberately lengthening the advertised path so
the local instance is preferred within its own AZ and the parallel
instance in another AZ only picks up traffic on failure. When a peer
goes down, BFD detects it and the surviving instance takes over the
route within roughly two seconds. The outcome Magnite reports: an 80%
reduction in NAT Gateway and Interface Endpoint dependency in their
highest-traffic region, converting variable per-GB NAT-processing
charges into more predictable EC2 instance cost.
The second pattern is active-active internal load balancing: HAProxy
nodes each own virtual IPs carved from unused VPC address space and
advertise them as /32 host routes, with BGP preference levels
expressing primary/backup ownership per VIP. Lose one node and route
server withdraws its /32s; traffic redistributes across the survivors
rather than cutting over all at once — Magnite measured roughly a 25%
load increase per surviving node from a single-node failure, a gradual
redistribution rather than a stampede onto whichever node happens to be
first in a health-check list.
Route Server also composes with Transit Gateway rather than replacing
it. A second AWS post from three days later, on centralized VPC
inspection,
shows the combination directly: Transit Gateway still does the
inter-VPC hub-and-spoke routing that gets traffic from spoke VPCs to a
shared inspection VPC, while Route Server inside that inspection VPC
runs active/standby firewall instances peered over BGP, with the active
instance advertising a shorter AS path (65550) than standby
(65550 65550) so the preference is explicit and Transit Gateway’s
route tables update automatically on failover. The same post describes
an AZ-affinity variant with one route server per Availability Zone,
keeping traffic local under normal conditions and only crossing AZs
during an actual failure — the same shape as Magnite’s MagNET pattern,
reused for firewall HA instead of NAT.
The footprint
BGP has always been the protocol AWS networking practitioners reached for at the edge — Direct Connect, Transit Gateway, on-premises peering — and never inside a VPC’s own subnets, because there was nothing there to peer with. Route Server closes that gap, and it changes the default answer to “how do I make this NAT instance, firewall, or software load balancer highly available inside a VPC” from “cron job plus the EC2 API, and hope the polling interval is short enough” to “advertise a route and let policy decide,” with BFD giving you failure detection measured in seconds rather than the ad-hoc thirty-to-sixty-second windows most health-check scripts settle for.
It is not a replacement for Transit Gateway, and the hundred-route, hundred-peer-route ceiling means it isn’t meant to hold an internet routing table either — it’s scoped, deliberately, to appliance high availability and intent-based failover within a VPC boundary. Design for that scope from the start the way Magnite says they wish they had: size the topology against the quotas before you commit to it, prefer AS-path prepending over MED tuning for anything a future on-call engineer needs to reason about at 3am, and build the routing pattern and its automation together rather than retrofitting monitoring onto a topology that was never designed to be observed.