Home Resume
Homeβ€Ί Blogβ€Ί AWS Daily Intelligence #1 - Policy-Based Routing o…
AWS Daily Intelligence AWS

Policy-Based Routing on AWS Transit Gateway: What Changes in Your Network Architecture

Transit Gateway has forwarded on the destination prefix alone since it launched. As of 30 July 2026 it can classify traffic on source IP, destination IP, port, and protocol, and send each class to a different route table. This is a genuinely architectural change, and it ships with two behaviours that will take traffic down if you meet them by surprise.

AWS Daily Intelligence Β· 3 August 2026

Executive summary

On 30 July 2026, AWS announced general availability of Policy-Based Routing (PBR) on AWS Transit Gateway. Since Transit Gateway launched, a forwarding decision has been a function of one variable: the destination prefix. PBR adds a second mechanism. You can now classify traffic on source CIDR, destination CIDR, source port, destination port, and protocol, and send each class to a different transit gateway route table.

The mechanism is a new resource, the transit gateway policy table. It is an ordered list of rules that you associate with an attachment. It does not sit alongside the route table on that attachment - it replaces it.

PBR is available in all AWS Regions where Transit Gateway is available, at no additional charge beyond standard Transit Gateway fees. It is enabled on all transit gateways by default; there is no feature flag to set.

Two consequences will surprise anyone who deploys it casually: unmatched traffic is dropped, and associating a policy table with a BGP-speaking attachment stops route advertisement to that peer. Both are covered below.

What changed

Before this launch, a transit gateway attachment was associated with exactly one route table, and that route table performed a longest-prefix-match lookup on the destination address. Two flows leaving the same VPC for the same destination were, by definition, treated identically. There was no supported way to make the transit gateway itself distinguish them.

A new resource: the policy table

A policy table contains an ordered set of rules. Each rule has match criteria and a target route table.

Five match attributes, all optional

Any attribute you omit defaults to Any (*):

AttributeValid valuesNotes
SourceCidrBlockIPv4 or IPv6 CIDRfor example 10.0.0.0/16
DestinationCidrBlockIPv4 or IPv6 CIDR
Protocol1 ICMPv4, 6 TCP, 17 UDP, 47 GRE, or *IANA protocol number
SourcePortRangeSingle port or range, 0-65535Only evaluated for TCP and UDP
DestinationPortRangeSingle port or range, 0-65535Only evaluated for TCP and UDP

Port ranges are only supported for TCP (6) and UDP (17). For ICMPv4, GRE, or Any, port ranges are automatically set to * and cannot be configured. Both IPv4 and IPv6 CIDR formats are supported.

First-match-wins evaluation

Customer-managed rules are numbered 1 to 50,000 and evaluated in ascending numeric order. The first rule that matches is applied and evaluation stops.

Two entry types

Customer-managed entries are the ones you create. System-managed entries are created and maintained by AWS to support internal routing functions such as AWS Cloud WAN segment isolation. System-managed entries display a rule number of *, are read-only, and are evaluated before all customer-managed entries. Both types are returned together by GetTransitGatewayPolicyTableEntries.

Attachment exclusivity

An attachment can be associated with either a policy table or a route table, never both. If the attachment already has a route table associated, the association request fails until you disassociate it.

Why AWS introduced it

The honest answer is that customers had been building this behaviour themselves, badly.

Consider the recurring requirement: inspect traffic from the PCI subnet with a firewall, but let everything else take the direct path. With destination-only routing, the transit gateway cannot express that rule, because both flows may share a destination. The workarounds were all structural:

  • Split the VPC. Move the sensitive workload into its own VPC so it gets its own attachment and therefore its own route table. This is a network design change forced by a routing limitation.
  • Proliferate route tables and attachments. Multiply attachments to create the granularity the route table could not provide. You run into design complexity long before you run into the quota of 20 route tables per transit gateway.
  • Push the decision down into the VPC. Use subnet route tables and Gateway Load Balancer endpoints to steer inside the VPC before traffic reaches the transit gateway. This works, but it distributes security policy across every VPC in the estate, which is what a centralised inspection architecture was meant to avoid.
  • Inspect everything. The most common resolution in practice. Send all traffic through the firewall because you cannot selectively send some of it. You pay for inspection capacity you do not need and add latency to flows that did not require it.

Each of these trades network design cleanliness, cost, or operational surface for a capability the routing layer should have provided. PBR moves the classification decision to the transit gateway, which is where traffic already converges and where the policy is easiest to audit.

Architecture

The mental model that matters: a policy table does not route traffic. It selects the route table that will.

Evaluation on an attachment associated with a policy table proceeds in three stages. System-managed entries are evaluated first, and if one matches it is applied regardless of any customer rule you configured. Customer-managed entries are evaluated next, in ascending rule number order, first match wins. If nothing matches, the packet is dropped.

Diagram: transit gateway policy table evaluation β€” system-managed entries are evaluated first, then customer entries in ascending rule number order with first match wins, and traffic matching no entry is dropped by implicit deny.

Once a rule matches, the selected route table performs an ordinary destination-based lookup. PBR classifies; the route table forwards. Nothing about route table semantics changes.

The return path deserves attention

In the AWS worked example, traffic from a sensitive subnet is steered to a firewall route table, the firewall inspects it, and forwards it back to the transit gateway. On return, the transit gateway re-evaluates the traffic using destination-based lookup on the route table associated with the firewall VPC attachment.

Read that again, because it is the single most important operational detail in the feature. The forward path is policy-classified. The return path is a normal route table lookup on a different attachment. You are responsible for making those two halves agree.

If you steer a flow through inspection in one direction but the return path takes the direct route, a stateful firewall will see half a conversation and drop it. Asymmetric routing was already the classic failure mode in centralised inspection designs; PBR gives you a much finer instrument, and therefore many more ways to create asymmetry. Design both directions deliberately, and treat "which route table does the return traffic hit" as a required question in every review.

Business value

Inspect selectively instead of universally. The clearest financial argument. If you are running all east-west traffic through a firewall fleet because you could not express a narrower rule, PBR lets you scope inspection to the flows that actually require it. Firewall throughput is one of the more expensive resources in an enterprise landing zone.

Stop deforming network design to satisfy routing constraints. VPCs that exist only because a workload needed its own route table are pure overhead: extra attachments, extra CIDR management, extra Terraform. PBR removes the reason they existed.

Express policy where it is auditable. A policy table associated with an attachment is a short, ordered, greppable list. A compliance reviewer can read it. The equivalent behaviour expressed across a dozen subnet route tables and Gateway Load Balancer endpoints cannot be reviewed with any confidence.

Differentiated paths for differentiated traffic. Routing a specific application over Direct Connect while general traffic uses VPN, based on source and port, is now a rule rather than a project.

Security considerations

Implicit deny is a security property and an availability risk. If no rule matches, the packet is dropped silently. This is the correct default for a security control and a genuine hazard during migration. AWS guidance is explicit: always include a catch-all rule at a high rule number if you want unmatched traffic to reach a route table rather than be dropped. Add the catch-all first, then add specific rules above it.

Rule ordering is the control. A broad rule at a low number shadows every more specific rule beneath it. A rule 10 of {} matching everything renders rules 20 through 50,000 dead. There is no analyser that will warn you. Order is reviewed by humans, so keep tables short and comment them in your IaC.

Match criteria are packet attributes, not identity. Source CIDR is not a principal. PBR is a traffic steering mechanism, not an authorization mechanism. It complements security groups, NACLs, and Network Firewall; it does not replace any of them. Do not let a policy table become the only thing standing between two segments.

System-managed entries can pre-empt your policy. If your policy table carries Cloud WAN segmentation entries, those are evaluated first and are read-only. Your rules apply only to traffic that does not match one. Verify the full table with GetTransitGatewayPolicyTableEntries rather than assuming the console shows only what you created.

Scope the IAM actions. PBR introduces a distinct set of ec2:*TransitGatewayPolicyTable* actions. Whoever can call ec2:CreateTransitGatewayPolicyTableEntry or ec2:AssociateTransitGatewayPolicyTable can redirect production traffic. These belong with your network administration role, not in a general developer policy.

Cost considerations

The feature is free. PBR incurs no additional charge beyond standard Transit Gateway fees. There is no per-rule or per-policy-table cost.

The traffic patterns it enables are not. Transit Gateway bills two ways: $0.05 per attachment-hour and $0.02 per GB of data processed. Both figures are US East (Ohio) as published on the Transit Gateway pricing page; rates vary by Region, so confirm your own before modelling.

The attachment charge is unaffected by PBR, since you are not adding attachments. The data processing charge is where steering shows up, and the billing model is the part worth understanding.

Data processing is charged per GB entering the transit gateway from a VPC, Direct Connect, VPN, or Network Firewall attachment. Traffic arriving from a peering attachment is not charged. Because the charge is per ingress rather than per flow, an inspection detour is billed twice: once when the packet enters from the source VPC, and again when the firewall VPC hands it back.

That doubling is exactly what PBR lets you stop paying on traffic that never needed inspecting. Take 100,000 GB per month of east-west traffic:

ApproachGB processed by TGWData processing cost
Inspect everything (the pre-PBR default)200,000$4,000 / month
Inspect 10%, steer the rest directly110,000$2,200 / month

Roughly $1,800 per month on this line item alone, at one Region's rates, before you count the firewall capacity you no longer need to provision. Scale it to your actual volume.

Three caveats on that arithmetic. It counts one direction, so add the return path. It excludes AWS Network Firewall's own endpoint-hour and per-GB charges, or your appliance fleet's cost, which is usually the larger number and moves the same direction. And it assumes your inspection VPC returns traffic to the transit gateway; a design that egresses directly from the inspection VPC bills differently.

Quota headroom is a design input, not a billing one. Policy table entries are capped at 200 per transit gateway across all policy tables (adjustable), and policy tables at 20 per transit gateway (not adjustable). A design that needs a rule per application will exhaust the entry quota in a large estate. Classify by CIDR range and port, not by individual workload.

Operational considerations

Migration is a cutover, not a rollout. Because an attachment cannot hold both a route table and a policy table, moving an attachment to PBR means disassociating the route table and associating the policy table. There is no side-by-side period and no shadow mode. Build and validate the policy table fully before you disassociate anything, and rehearse the reverse operation.

Verify before you route live traffic. After every change, read the table back with GetTransitGatewayPolicyTableEntries and confirm rule numbers and match conditions, including system entries you did not create.

Number with gaps. AWS recommends increments of 10 or 100 so you can insert rules later without renumbering. Renumbering an ordered ruleset under change control is unpleasant, and the customer range is 1 to 50,000, so there is no reason to be frugal.

Your existing troubleshooting instincts are now incomplete. "Which route table is this attachment associated with, and what does it say about this destination?" is no longer a sufficient diagnosis. The new question is which rule matched. Update runbooks accordingly - this is the kind of change where a 3 a.m. responder loses an hour to a model that no longer fits.

Direct Connect BGP visibility pairs well with this. AWS also shipped BGP route visibility on Direct Connect Virtual Interfaces on 30 July, exposing accepted and advertised routes with AS path and community values through the console and the ListVirtualInterfaceRoutes API. If you are steering traffic across Direct Connect with PBR, that is the tool that tells you what the other side actually received.

Tradeoffs

Against Gateway Load Balancer with VPC-level steering. GWLB steers inside the VPC and is transparent to the transit gateway. It remains the right tool when inspection must happen close to the workload, or when the appliance must see traffic that never reaches the transit gateway. PBR centralises the decision at the transit gateway, which is better for estate-wide policy and worse for VPC-local nuance. They compose; this is not an either/or.

Against AWS Cloud WAN. Cloud WAN expresses intent as segments and policy documents across a global network. PBR is per-attachment and per-Region. If you are already running Cloud WAN, its segmentation model should remain primary - and note that on TGW-to-Cloud WAN peering attachments, customer-managed PBR entries are not supported at all.

Against splitting VPCs. A separate VPC gives hard isolation, its own security group namespace, and its own blast radius. A PBR rule gives routing differentiation only. If the requirement is genuine isolation, the VPC split is still the right answer.

Complexity is relocated, not eliminated. You are trading a large number of simple objects (route tables, attachments) for a smaller number of ordered, stateful rulesets. Ordered rulesets are compact and expressive, and they fail in ways that are harder to see. Anyone who has debugged a long firewall ruleset knows the shape of the problem.

Implementation guidance

Prerequisites

  • An existing transit gateway. PBR is enabled on all transit gateways by default; no activation step is required.
  • The target transit gateway route tables must already exist.
  • If the attachment is currently associated with a route table, disassociate it first.
  • IAM permissions for the PBR actions: ec2:CreateTransitGatewayPolicyTable, ec2:DescribeTransitGatewayPolicyTables, ec2:DeleteTransitGatewayPolicyTable, ec2:AssociateTransitGatewayPolicyTable, ec2:DisassociateTransitGatewayPolicyTable, ec2:GetTransitGatewayPolicyTableAssociations, ec2:GetTransitGatewayPolicyTableEntries, ec2:CreateTransitGatewayPolicyTableEntry, ec2:ModifyTransitGatewayPolicyTableEntry, ec2:DeleteTransitGatewayPolicyTableEntry.

Worked example: steer one subnet through inspection

Requirement: traffic from 10.1.10.0/24 must pass through a firewall VPC; everything else forwards normally.

Rule #Source CIDRDest CIDRProtocolSrc portDst portTarget route table
10010.1.10.0/24AnyAnyAnyAnytgw-rtb-firewall
200AnyAnyAnyAnyAnytgw-rtb-default

Create the policy table:

aws ec2 create-transit-gateway-policy-table \
    --transit-gateway-id tgw-0bc994abffEXAMPLE

Add the catch-all first, so the table is never in a state where it drops everything:

aws ec2 create-transit-gateway-policy-table-entry \
    --transit-gateway-policy-table-id tgw-ptb-0ca78a549EXAMPLE \
    --policy-rule-number 200 \
    --policy-rule '{}' \
    --target-route-table-id tgw-rtb-default

Add the specific steering rule above it:

aws ec2 create-transit-gateway-policy-table-entry \
    --transit-gateway-policy-table-id tgw-ptb-0ca78a549EXAMPLE \
    --policy-rule-number 100 \
    --policy-rule '{"SourceCidrBlock": "10.1.10.0/24"}' \
    --target-route-table-id tgw-rtb-firewall

Verify the full table, including any system-managed entries:

aws ec2 get-transit-gateway-policy-table-entries \
    --transit-gateway-policy-table-id tgw-ptb-0ca78a549EXAMPLE

Only then associate it with the attachment:

aws ec2 associate-transit-gateway-policy-table \
    --transit-gateway-policy-table-id tgw-ptb-0ca78a549EXAMPLE \
    --transit-gateway-attachment-id tgw-attach-0def6EXAMPLE

A rule matching HTTPS to a specific destination looks like this:

aws ec2 create-transit-gateway-policy-table-entry \
    --transit-gateway-policy-table-id tgw-ptb-0ca78a549EXAMPLE \
    --policy-rule-number 100 \
    --policy-rule '{"SourceCidrBlock": "10.100.0.0/16", "Protocol": "6", "DestinationPortRange": "443"}' \
    --target-route-table-id tgw-rtb-0a823edbdeEXAMPLE

Easy to get wrong. Protocol must be 6 or 17 for the port range fields to be evaluated at all. A rule specifying a destination port with Protocol omitted will not behave the way its author intended.

Best practices

  1. Always include a catch-all rule at a high rule number unless silent drop is the behaviour you want. Create it before the specific rules.
  2. Leave gaps between rule numbers, in increments of 10 or 100.
  3. Most specific rules at the lowest numbers. A broad rule at a low number shadows everything below it.
  4. Set protocol before configuring port ranges. Port ranges are only active for TCP (6) and UDP (17).
  5. Read the table back after every change with GetTransitGatewayPolicyTableEntries, and account for system-managed entries.
  6. Design the return path explicitly. Return traffic is re-evaluated by destination lookup on the route table associated with the inspection attachment, not by your policy table.
  7. Keep policy tables short. The 200-entry-per-transit-gateway quota and human reviewability both point the same direction.
  8. Manage policy tables in IaC with comments explaining rule order. Rule numbers encode intent that the API does not capture.

Who should adopt, who should wait

Adopt

  • Teams running centralised inspection architectures who currently inspect everything because they cannot inspect selectively. This is the primary case, and the cost argument is usually immediate.
  • Organisations that have created VPCs or attachments purely to obtain routing granularity.
  • Teams with hybrid connectivity needing to route specific applications over Direct Connect and everything else over VPN, differentiated by source or port.
  • Regulated environments that must demonstrate a specific traffic class is inspected, and want that assertion to live in one reviewable ordered list.

Wait

  • Anyone whose destination-based routing already expresses their requirements. PBR adds ordered-ruleset complexity that is a liability with no offsetting benefit.
  • Teams without an asymmetric-routing testing capability. If you cannot verify both directions of a flow in a non-production environment, do not put this in front of production traffic.
  • Site-to-Site VPN and Transit Gateway Connect attachments that depend on TGW-advertised BGP routes. See the next section - this is a hard blocker, not a caution.
  • AWS Cloud WAN peering attachments, where customer-managed PBR entries are not supported.
  • Anyone who would deploy it without updating runbooks.

The limitation most likely to cause an outage

This deserves its own section because it is easy to miss and expensive to discover in production.

Associate a policy table with a Site-to-Site VPN or Transit Gateway Connect attachment, and the transit gateway stops advertising routes to that peer entirely. Not a reduced set, not a filtered subset - the attachment advertises nothing.

If your on-premises router or SD-WAN appliance learns AWS prefixes dynamically from the transit gateway, associating a policy table with that attachment will silently remove them. The attachment stays up. BGP stays established. The routes stop arriving.

Direct Connect is the exception, and the reason is worth understanding rather than memorising. What a transit gateway advertises to your customer gateway over Direct Connect is determined by the allowed-prefixes list on the Direct Connect gateway association, a different mechanism entirely from the attachment-level advertisement that a policy table suppresses. Associating a policy table leaves those advertisements untouched.

Turn this into a review gate. Any change that associates a policy table with a dynamically-routed attachment should require evidence that the peer does not depend on transit gateway BGP advertisement, captured before the change rather than discovered after it. AWS documents the same precondition in its limitations page.

Two further launch limitations. TGW-to-Cloud WAN peering attachments do not support customer-managed entries; traffic on those attachments is controlled exclusively by system-managed entries, though you can still add customer entries to the same policy table for use with other attachment types. And system-managed entries cannot be modified or deleted by customers at this time.

Key takeaways

  1. Transit Gateway forwarding is no longer destination-only. Policy tables classify on source CIDR, destination CIDR, protocol, source port, and destination port, then select a route table.
  2. A policy table replaces the route table on an attachment. There is no side-by-side mode, so migration is a cutover.
  3. Unmatched traffic is dropped. Create the catch-all rule first.
  4. Associating a policy table with a VPN or Connect attachment stops BGP advertisement to that peer. Direct Connect is unaffected.
  5. Return traffic is re-evaluated by ordinary destination lookup on the inspection attachment's route table. Asymmetry is now easier to create.
  6. System-managed entries are evaluated before yours and are read-only.
  7. GA in all Regions where Transit Gateway is available, enabled by default, no additional charge. The traffic patterns it enables do carry data processing costs.
  8. Quotas: 20 policy tables per transit gateway (not adjustable), 200 entries per transit gateway across all policy tables (adjustable), rule numbers 1 to 50,000.

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent