BGP Route Manipulation with LOCAL_PREF: Choosing How Traffic Leaves Your AS
Every dual-homed network eventually asks the same question: we pay for two upstream circuits, so which one actually carries our traffic? BGP will happily answer that for you, and its answer is usually wrong. It picks the shortest AS_PATH, which has nothing to do with your contracts, your bandwidth, or your latency. LOCAL_PREF is how you overrule it.
Outbound or inbound? Get the direction right
This is the most common source of confusion in BGP traffic engineering, so it is worth stating plainly. LOCAL_PREF influences traffic leaving your AS: it tells your own routers which exit to use for a given destination. AS_PATH prepending, MED and communities influence traffic entering your AS: they are hints you send to other people's routers, and those routers are free to ignore them.
If your problem statement is "downloads are slow", you are looking at inbound traffic and LOCAL_PREF is the wrong tool. If it is "our outbound traffic to a partner should never cross the backup circuit", you are in the right place.
What LOCAL_PREF actually is
LOCAL_PREF is a well-known discretionary path attribute, type code 5. Three properties define its behaviour.
Higher wins
Unlike almost everything else in BGP best-path selection, LOCAL_PREF is a highest-wins comparison. The default on both Cisco and Junos is 100, so any value above that steers traffic towards the path carrying it.
It never leaves your AS
A router includes LOCAL_PREF in updates it sends to iBGP peers and strips it from updates sent to eBGP peers. That is why the whole AS can agree on a single exit point, and why your neighbour's network never sees the value you set.
It is evaluated before AS_PATH
In the Cisco best-path algorithm the order is roughly: highest weight, then highest LOCAL_PREF, then locally originated, then shortest AS_PATH, then lowest origin, then lowest MED, then eBGP over iBGP, then lowest IGP metric to the next hop, and finally the tiebreakers. Because LOCAL_PREF sits above AS_PATH, it beats topology.
The practical consequence is that LOCAL_PREF is the only attribute that gives you a consistent, AS-wide exit policy. Weight would also work on a single router, but weight is Cisco-proprietary and never leaves the box it is configured on. Set weight on R1, and R2 keeps routing traffic its own way.
The classic scenario: primary and backup transit
In the topology at the top of this article, AS 65001 buys transit from ISP-A on R1 and from ISP-B on R2. Both upstreams advertise the full table, including 198.51.100.0/24. R1 applies an inbound policy that stamps LOCAL_PREF 200 on everything it learns from ISP-A. R2 does nothing, so its paths carry the default 100.
R1 and R2 exchange these paths over iBGP with the LOCAL_PREF intact. Every BGP speaker in AS 65001 now compares 200 against 100 and installs the ISP-A path, so all outbound traffic converges on R1 regardless of which upstream has the shorter AS_PATH. If the ISP-A session drops, those paths are withdrawn, the ISP-B paths become the only candidates, and the AS fails over to R2 with no configuration change.
Cisco IOS-XE
ip prefix-list ANY seq 5 permit 0.0.0.0/0 le 32!route-map ISP-A-IN permit 10description Prefer ISP-A for all outbound trafficmatch ip address prefix-list ANYset local-preference 200!router bgp 65001neighbor 192.0.2.1 remote-as 64500neighbor 10.0.255.2 remote-as 65001address-family ipv4 unicastneighbor 192.0.2.1 activateneighbor 192.0.2.1 route-map ISP-A-IN inneighbor 10.0.255.2 activateneighbor 10.0.255.2 next-hop-selfexit-address-family
You can get the same result without a route-map by configuring bgp default local-preference 200 under the BGP process, which changes the default for every path that router learns. It is shorter, but it is also blunt: it applies to iBGP-learned paths too, and it is easy to forget when you later add a third neighbour. On anything maintained by more than one person, prefer the explicit route-map.
Junos
set policy-options policy-statement ISP-A-IN term prefer-isp-a then local-preference 200set policy-options policy-statement ISP-A-IN term prefer-isp-a then acceptset protocols bgp group ISP-A type externalset protocols bgp group ISP-A peer-as 64500set protocols bgp group ISP-A import ISP-A-INset protocols bgp group ISP-A neighbor 192.0.2.1set protocols bgp group INTERNAL type internalset protocols bgp group INTERNAL local-address 10.0.255.1set protocols bgp group INTERNAL neighbor 10.0.255.2
Note the difference in default behaviour between the two vendors. A Cisco route-map with a match statement and no final permit clause denies every prefix that did not match. That implicit deny has blackholed more than one production network during a maintenance window. Junos import policies fall through to the BGP default, which is accept for eBGP, when no term matches, so partial policies fail more gracefully there.
Being selective: per-prefix steering
Full-table LOCAL_PREF is the easy case. The interesting work is steering specific destinations, for example sending traffic for a partner's prefix out of the circuit with lower latency while everything else keeps its normal path.
ip prefix-list PARTNER-PFX seq 5 permit 198.51.100.0/24!route-map ISP-A-IN permit 10match ip address prefix-list PARTNER-PFXset local-preference 300!route-map ISP-A-IN permit 20description Everything else keeps the default
Sequence 20 exists purely to defeat the implicit deny. Leave it out and you have just filtered the entire internet.
Tagging with communities
In a larger AS with several edge routers, tagging at the edge and acting in the core scales far better than maintaining prefix lists everywhere. The edge router marks paths with a community, and one shared iBGP inbound policy translates communities into preference values.
ip community-list standard LP-PRIMARY permit 65001:200ip community-list standard LP-BACKUP permit 65001:100!route-map IBGP-IN permit 10match community LP-PRIMARYset local-preference 200!route-map IBGP-IN permit 20match community LP-BACKUPset local-preference 50!route-map IBGP-IN permit 30
Many transit providers offer the mirror image of this as a customer service: send them a documented community and they lower LOCAL_PREF inside their own AS, which is one of the few ways to genuinely influence inbound traffic. Check your provider's published community list before prepending AS_PATH out of habit.
Verifying the result
Configuration that has not been verified in the forwarding table is a hypothesis.
show bgp ipv4 unicast 198.51.100.0/24show bgp ipv4 unicast neighbors 192.0.2.1 routesshow ip route 198.51.100.1
In the per-prefix output the chosen path is the one marked best, and the reason should read as Local Pref 200. Confirm that the next hop resolves through the interface you expect. A correct BGP decision with an unreachable next hop still gets you nothing. On Junos the equivalents are show route 198.51.100.0/24 detail and show route receive-protocol bgp 192.0.2.1.
Policy changes do not apply retroactively to paths already in the table. After editing an inbound policy on Cisco, refresh the session with clear bgp ipv4 unicast 192.0.2.1 soft in. That uses the route-refresh capability, which every modern peer negotiates, so there is no session teardown and no re-convergence event. On Junos, commit triggers the equivalent refresh automatically.
Five ways this goes wrong in production
Weight silently wins
If someone configured neighbor 192.0.2.1 weight 100 years ago on one router, your carefully designed LOCAL_PREF policy applies everywhere except there. Weight is checked first and is invisible from any other device. Audit for it before you troubleshoot anything else.
The backup circuit was never sized for the load
A 1 Gbps primary and a 100 Mbps backup with equal LOCAL_PREF is a slow-motion outage waiting for a fibre cut. Decide deliberately whether failover means degraded but up, and whether you need policy to shed non-critical traffic when it happens.
Return traffic does not follow
LOCAL_PREF is invisible outside your AS, so the far end still picks its own path back. Asymmetric routing is normal for BGP, but it breaks stateful middleboxes that expect to see both directions. If you have firewalls at both edges, either accept asymmetry in the design or pair LOCAL_PREF with inbound influence tools.
An iBGP gap splits the decision
LOCAL_PREF only produces an AS-wide decision if it actually reaches every speaker. A missing iBGP session, a route-reflector cluster misconfiguration, or a reflector policy that resets preference will leave part of your network exiting through the wrong router. Check the value on a leaf router, not just on the edge.
Setting it outbound does nothing
Using set local-preference in an outbound policy on an eBGP session is not an error and produces no result, because the attribute is stripped on the way out. If you see that in a config, someone was reaching for AS_PATH prepending or a provider community.
The takeaway
LOCAL_PREF is the primary lever for outbound BGP policy: higher wins, it is compared before AS_PATH, and it stays inside your AS. Apply it inbound on your eBGP sessions, propagate it over a healthy iBGP mesh, and verify it on a router far from where you configured it. Reach for communities rather than prefix lists once you have more than a couple of edge devices, and never write a Cisco route-map without asking what happens to the prefixes that did not match.
Build it in a lab first. Two edge routers, two upstream ASes, one prefix, and a show bgp before and after. Half an hour of that teaches more than any diagram, including the one above.
Every dual-homed network eventually asks the same question: we pay for two upstream circuits, so which one actually carries our traffic? BGP will happily answer that for you, and its answer is usually wrong. It picks the shortest AS_PATH, which has nothing to do with your contracts, your bandwidth, or your latency. LOCAL_PREF is how you overrule it.
Outbound or inbound? Get the direction right
This is the most common source of confusion in BGP traffic engineering, so it is worth stating plainly. LOCAL_PREF influences traffic leaving your AS: it tells your own routers which exit to use for a given destination. AS_PATH prepending, MED and communities influence traffic entering your AS: they are hints you send to other people's routers, and those routers are free to ignore them.
If your problem statement is "downloads are slow", you are looking at inbound traffic and LOCAL_PREF is the wrong tool. If it is "our outbound traffic to a partner should never cross the backup circuit", you are in the right place.
What LOCAL_PREF actually is
LOCAL_PREF is a well-known discretionary path attribute, type code 5. Three properties define its behaviour.
Higher wins
Unlike almost everything else in BGP best-path selection, LOCAL_PREF is a highest-wins comparison. The default on both Cisco and Junos is 100, so any value above that steers traffic towards the path carrying it.
It never leaves your AS
A router includes LOCAL_PREF in updates it sends to iBGP peers and strips it from updates sent to eBGP peers. That is why the whole AS can agree on a single exit point, and why your neighbour's network never sees the value you set.
It is evaluated before AS_PATH
In the Cisco best-path algorithm the order is roughly: highest weight, then highest LOCAL_PREF, then locally originated, then shortest AS_PATH, then lowest origin, then lowest MED, then eBGP over iBGP, then lowest IGP metric to the next hop, and finally the tiebreakers. Because LOCAL_PREF sits above AS_PATH, it beats topology.
The practical consequence is that LOCAL_PREF is the only attribute that gives you a consistent, AS-wide exit policy. Weight would also work on a single router, but weight is Cisco-proprietary and never leaves the box it is configured on. Set weight on R1, and R2 keeps routing traffic its own way.
The classic scenario: primary and backup transit
In the topology at the top of this article, AS 65001 buys transit from ISP-A on R1 and from ISP-B on R2. Both upstreams advertise the full table, including 198.51.100.0/24. R1 applies an inbound policy that stamps LOCAL_PREF 200 on everything it learns from ISP-A. R2 does nothing, so its paths carry the default 100.
R1 and R2 exchange these paths over iBGP with the LOCAL_PREF intact. Every BGP speaker in AS 65001 now compares 200 against 100 and installs the ISP-A path, so all outbound traffic converges on R1 regardless of which upstream has the shorter AS_PATH. If the ISP-A session drops, those paths are withdrawn, the ISP-B paths become the only candidates, and the AS fails over to R2 with no configuration change.
Cisco IOS-XE
ip prefix-list ANY seq 5 permit 0.0.0.0/0 le 32!route-map ISP-A-IN permit 10description Prefer ISP-A for all outbound trafficmatch ip address prefix-list ANYset local-preference 200!router bgp 65001neighbor 192.0.2.1 remote-as 64500neighbor 10.0.255.2 remote-as 65001address-family ipv4 unicastneighbor 192.0.2.1 activateneighbor 192.0.2.1 route-map ISP-A-IN inneighbor 10.0.255.2 activateneighbor 10.0.255.2 next-hop-selfexit-address-family
You can get the same result without a route-map by configuring bgp default local-preference 200 under the BGP process, which changes the default for every path that router learns. It is shorter, but it is also blunt: it applies to iBGP-learned paths too, and it is easy to forget when you later add a third neighbour. On anything maintained by more than one person, prefer the explicit route-map.
Junos
set policy-options policy-statement ISP-A-IN term prefer-isp-a then local-preference 200set policy-options policy-statement ISP-A-IN term prefer-isp-a then acceptset protocols bgp group ISP-A type externalset protocols bgp group ISP-A peer-as 64500set protocols bgp group ISP-A import ISP-A-INset protocols bgp group ISP-A neighbor 192.0.2.1set protocols bgp group INTERNAL type internalset protocols bgp group INTERNAL local-address 10.0.255.1set protocols bgp group INTERNAL neighbor 10.0.255.2
Note the difference in default behaviour between the two vendors. A Cisco route-map with a match statement and no final permit clause denies every prefix that did not match. That implicit deny has blackholed more than one production network during a maintenance window. Junos import policies fall through to the BGP default, which is accept for eBGP, when no term matches, so partial policies fail more gracefully there.
Being selective: per-prefix steering
Full-table LOCAL_PREF is the easy case. The interesting work is steering specific destinations, for example sending traffic for a partner's prefix out of the circuit with lower latency while everything else keeps its normal path.
ip prefix-list PARTNER-PFX seq 5 permit 198.51.100.0/24!route-map ISP-A-IN permit 10match ip address prefix-list PARTNER-PFXset local-preference 300!route-map ISP-A-IN permit 20description Everything else keeps the default
Sequence 20 exists purely to defeat the implicit deny. Leave it out and you have just filtered the entire internet.
Tagging with communities
In a larger AS with several edge routers, tagging at the edge and acting in the core scales far better than maintaining prefix lists everywhere. The edge router marks paths with a community, and one shared iBGP inbound policy translates communities into preference values.
ip community-list standard LP-PRIMARY permit 65001:200ip community-list standard LP-BACKUP permit 65001:100!route-map IBGP-IN permit 10match community LP-PRIMARYset local-preference 200!route-map IBGP-IN permit 20match community LP-BACKUPset local-preference 50!route-map IBGP-IN permit 30
Many transit providers offer the mirror image of this as a customer service: send them a documented community and they lower LOCAL_PREF inside their own AS, which is one of the few ways to genuinely influence inbound traffic. Check your provider's published community list before prepending AS_PATH out of habit.
Verifying the result
Configuration that has not been verified in the forwarding table is a hypothesis.
show bgp ipv4 unicast 198.51.100.0/24show bgp ipv4 unicast neighbors 192.0.2.1 routesshow ip route 198.51.100.1
In the per-prefix output the chosen path is the one marked best, and the reason should read as Local Pref 200. Confirm that the next hop resolves through the interface you expect. A correct BGP decision with an unreachable next hop still gets you nothing. On Junos the equivalents are show route 198.51.100.0/24 detail and show route receive-protocol bgp 192.0.2.1.
Policy changes do not apply retroactively to paths already in the table. After editing an inbound policy on Cisco, refresh the session with clear bgp ipv4 unicast 192.0.2.1 soft in. That uses the route-refresh capability, which every modern peer negotiates, so there is no session teardown and no re-convergence event. On Junos, commit triggers the equivalent refresh automatically.
Five ways this goes wrong in production
Weight silently wins
If someone configured neighbor 192.0.2.1 weight 100 years ago on one router, your carefully designed LOCAL_PREF policy applies everywhere except there. Weight is checked first and is invisible from any other device. Audit for it before you troubleshoot anything else.
The backup circuit was never sized for the load
A 1 Gbps primary and a 100 Mbps backup with equal LOCAL_PREF is a slow-motion outage waiting for a fibre cut. Decide deliberately whether failover means degraded but up, and whether you need policy to shed non-critical traffic when it happens.
Return traffic does not follow
LOCAL_PREF is invisible outside your AS, so the far end still picks its own path back. Asymmetric routing is normal for BGP, but it breaks stateful middleboxes that expect to see both directions. If you have firewalls at both edges, either accept asymmetry in the design or pair LOCAL_PREF with inbound influence tools.
An iBGP gap splits the decision
LOCAL_PREF only produces an AS-wide decision if it actually reaches every speaker. A missing iBGP session, a route-reflector cluster misconfiguration, or a reflector policy that resets preference will leave part of your network exiting through the wrong router. Check the value on a leaf router, not just on the edge.
Setting it outbound does nothing
Using set local-preference in an outbound policy on an eBGP session is not an error and produces no result, because the attribute is stripped on the way out. If you see that in a config, someone was reaching for AS_PATH prepending or a provider community.
The takeaway
LOCAL_PREF is the primary lever for outbound BGP policy: higher wins, it is compared before AS_PATH, and it stays inside your AS. Apply it inbound on your eBGP sessions, propagate it over a healthy iBGP mesh, and verify it on a router far from where you configured it. Reach for communities rather than prefix lists once you have more than a couple of edge devices, and never write a Cisco route-map without asking what happens to the prefixes that did not match.
Build it in a lab first. Two edge routers, two upstream ASes, one prefix, and a show bgp before and after. Half an hour of that teaches more than any diagram, including the one above.