<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Berik Ashimov</title>
    <description>The latest articles on DEV Community by Berik Ashimov (@ashimov).</description>
    <link>https://dev.to/ashimov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F985440%2Fdf4ff69f-13bb-4ebe-b054-c238dbafa68c.jpeg</url>
      <title>DEV Community: Berik Ashimov</title>
      <link>https://dev.to/ashimov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashimov"/>
    <language>en</language>
    <item>
      <title>Why Developers Are Looking Beyond the Cloud</title>
      <dc:creator>Berik Ashimov</dc:creator>
      <pubDate>Sat, 23 May 2026 19:13:55 +0000</pubDate>
      <link>https://dev.to/ashimov/why-developers-are-looking-beyond-the-cloud-51bj</link>
      <guid>https://dev.to/ashimov/why-developers-are-looking-beyond-the-cloud-51bj</guid>
      <description>&lt;p&gt;For years, the default advice was simple: move everything to the cloud.&lt;/p&gt;

&lt;p&gt;Need compute? Use the cloud.&lt;br&gt;
Need storage? Use the cloud.&lt;br&gt;
Need databases, queues, observability, networking, backups, and security? Use managed services.&lt;/p&gt;

&lt;p&gt;That advice made sense for a long time. Cloud platforms changed how software was built. They made infrastructure programmable, global, fast to deploy, and accessible to small teams without large capital investment. A startup could launch worldwide without buying a single server. A developer could create a production environment in minutes.&lt;/p&gt;

&lt;p&gt;But something interesting is happening now.&lt;/p&gt;

&lt;p&gt;Many engineering teams are quietly becoming more selective. They are not abandoning the cloud, but they are no longer treating it as the automatic answer to every infrastructure problem. Bare metal is coming back. Private cloud is being reconsidered. Edge infrastructure is growing. Developers are paying more attention to cost, latency, data control, portability, and operational independence.&lt;/p&gt;

&lt;p&gt;The new trend is not anti cloud. It is cloud maturity.&lt;/p&gt;

&lt;p&gt;The cloud was never magic&lt;/p&gt;

&lt;p&gt;The cloud solved real problems, but it also created new ones.&lt;/p&gt;

&lt;p&gt;At first, the value was obvious. Instead of waiting weeks for hardware, teams could deploy instantly. Instead of guessing capacity, they could scale on demand. Instead of building everything from scratch, they could consume managed services.&lt;/p&gt;

&lt;p&gt;But over time, many organizations discovered that convenience has a price.&lt;/p&gt;

&lt;p&gt;Cloud bills can become unpredictable. Managed services can create deep vendor lock in. Data transfer fees can turn architecture decisions into financial surprises. Debugging distributed systems across many managed components can become harder than managing a smaller, simpler platform.&lt;/p&gt;

&lt;p&gt;The cloud did not remove infrastructure complexity. It changed where that complexity lives.&lt;/p&gt;

&lt;p&gt;For a small team, that tradeoff is often worth it. For a growing company with stable workloads, high traffic, heavy storage, or strict compliance requirements, the equation starts to change.&lt;/p&gt;

&lt;p&gt;Predictable workloads do not always need elastic pricing&lt;/p&gt;

&lt;p&gt;One of the strongest arguments for the cloud is elasticity. If demand changes constantly, paying for resources as you use them is powerful.&lt;/p&gt;

&lt;p&gt;But not every workload is unpredictable.&lt;/p&gt;

&lt;p&gt;Many applications have steady traffic. Internal platforms, analytics pipelines, databases, monitoring systems, storage clusters, CI runners, media processing jobs, and enterprise services often run 24 hours a day with fairly known capacity needs.&lt;/p&gt;

&lt;p&gt;In these cases, renting infrastructure forever may not be the most efficient model.&lt;/p&gt;

&lt;p&gt;A dedicated server that runs at high utilization can be dramatically more cost effective than equivalent cloud resources. A small private cluster can handle predictable workloads with lower monthly cost and more control. Even colocation, which once felt old fashioned, is becoming attractive again for teams that understand their baseline capacity.&lt;/p&gt;

&lt;p&gt;This does not mean every company should buy racks of servers. It means engineers should ask better questions.&lt;/p&gt;

&lt;p&gt;Is this workload variable or stable?&lt;br&gt;
Does it need global elasticity or predictable capacity?&lt;br&gt;
Are we paying for convenience, or are we paying because nobody reviewed the architecture?&lt;br&gt;
Would a hybrid model reduce cost without increasing risk?&lt;/p&gt;

&lt;p&gt;The future belongs to teams that can answer these questions clearly.&lt;/p&gt;

&lt;p&gt;Latency is becoming a product feature&lt;/p&gt;

&lt;p&gt;Infrastructure decisions are no longer only about cost. They are also about user experience.&lt;/p&gt;

&lt;p&gt;Modern users expect applications to feel instant. A few hundred milliseconds can change how a product feels. For gaming, collaboration tools, trading platforms, video, IoT, payment systems, and real time dashboards, latency is not a technical detail. It is part of the product.&lt;/p&gt;

&lt;p&gt;This is one reason edge infrastructure is growing.&lt;/p&gt;

&lt;p&gt;When compute moves closer to users, applications can respond faster. When data processing happens near the source, systems can avoid unnecessary round trips. When services are deployed regionally, reliability improves because one central location is no longer the only path.&lt;/p&gt;

&lt;p&gt;The cloud is still important here, but it is not the whole story. Edge nodes, regional data centers, CDN compute, private points of presence, and local processing are becoming part of modern architecture.&lt;/p&gt;

&lt;p&gt;The best infrastructure is not always the biggest. Sometimes it is simply closer.&lt;/p&gt;

&lt;p&gt;Developers want portability again&lt;/p&gt;

&lt;p&gt;A few years ago, many teams were comfortable building deeply around one cloud provider. Managed databases, serverless functions, proprietary queues, cloud specific IAM, hosted observability, and provider specific deployment models made development faster.&lt;/p&gt;

&lt;p&gt;But the cost of that speed often appeared later.&lt;/p&gt;

&lt;p&gt;When everything depends on one provider’s unique services, moving becomes difficult. Even testing locally can become complicated. Engineers may understand the application code but not the platform behavior around it. A simple migration can turn into a long and expensive rewrite.&lt;/p&gt;

&lt;p&gt;This is why portability is becoming valuable again.&lt;/p&gt;

&lt;p&gt;Containers, Kubernetes, Terraform, OpenTofu, PostgreSQL, object storage compatible APIs, standard observability formats, and open networking tools are popular because they give teams options. They allow workloads to run in more than one environment. They also reduce the fear of being trapped.&lt;/p&gt;

&lt;p&gt;Portability does not mean pretending every platform is identical. It means designing systems so that the business has choices.&lt;/p&gt;

&lt;p&gt;A portable system can run in the cloud today, on bare metal tomorrow, and across multiple regions when needed. That flexibility is not just technical. It is strategic.&lt;/p&gt;

&lt;p&gt;Compliance and data control matter more than ever&lt;/p&gt;

&lt;p&gt;For regulated industries, infrastructure is not only about performance and cost. It is also about control.&lt;/p&gt;

&lt;p&gt;Finance, healthcare, telecom, government, and critical infrastructure companies must think carefully about where data lives, how it moves, who can access it, how logs are stored, and how systems are audited.&lt;/p&gt;

&lt;p&gt;Cloud providers offer strong security capabilities, but responsibility still belongs to the organization using them. Misconfigured storage, overly broad permissions, unclear network boundaries, and weak audit processes can still create serious risk.&lt;/p&gt;

&lt;p&gt;Some workloads are easier to govern when they run in a more controlled environment. Others benefit from managed cloud security services. The point is not that one model is always better. The point is that infrastructure should match the regulatory reality of the application.&lt;/p&gt;

&lt;p&gt;For developers, this means security and compliance can no longer be treated as something that happens after deployment. They must be part of architecture from the beginning.&lt;/p&gt;

&lt;p&gt;Where does the data live?&lt;br&gt;
Who can access it?&lt;br&gt;
What happens during an incident?&lt;br&gt;
Can we prove how the system behaves?&lt;br&gt;
Can we rebuild it from code?&lt;br&gt;
Can we audit every important change?&lt;/p&gt;

&lt;p&gt;These questions are becoming normal engineering questions.&lt;/p&gt;

&lt;p&gt;Simplicity is becoming a competitive advantage&lt;/p&gt;

&lt;p&gt;One of the biggest lessons of the last decade is that complexity scales faster than teams expect.&lt;/p&gt;

&lt;p&gt;A system can start with a simple architecture and slowly turn into dozens of services, queues, functions, databases, secrets, dashboards, policies, and deployment pipelines. Each part may make sense individually, but together they become hard to reason about.&lt;/p&gt;

&lt;p&gt;This is why many senior engineers are rediscovering the value of boring infrastructure.&lt;/p&gt;

&lt;p&gt;Boring does not mean outdated. It means understandable, reliable, documented, and easy to operate.&lt;/p&gt;

&lt;p&gt;A boring PostgreSQL database is often better than five specialized data services.&lt;br&gt;
A boring Linux server can be better than a fragile chain of managed components.&lt;br&gt;
A boring deployment pipeline can be better than a platform nobody fully understands.&lt;br&gt;
A boring network design can be better than a clever one that fails in strange ways.&lt;/p&gt;

&lt;p&gt;The best infrastructure is not the one that looks most impressive in a diagram. It is the one that survives real production pressure.&lt;/p&gt;

&lt;p&gt;The rise of hybrid thinking&lt;/p&gt;

&lt;p&gt;The most practical teams are not choosing between cloud and bare metal as a matter of ideology. They are using both.&lt;/p&gt;

&lt;p&gt;A common pattern is emerging:&lt;/p&gt;

&lt;p&gt;Cloud for burst capacity, global reach, managed services, and fast experimentation.&lt;br&gt;
Bare metal or private cloud for stable workloads, databases, storage, CI, and cost sensitive systems.&lt;br&gt;
Edge infrastructure for latency sensitive workloads.&lt;br&gt;
Open source tooling for portability and control.&lt;br&gt;
Automation everywhere to keep operations repeatable.&lt;/p&gt;

&lt;p&gt;This hybrid approach requires more engineering discipline, but it can produce better results. Teams get the speed of cloud where it matters and the efficiency of owned or dedicated infrastructure where it makes sense.&lt;/p&gt;

&lt;p&gt;The key is automation. Without automation, hybrid infrastructure becomes chaos. With automation, it becomes a flexible platform.&lt;/p&gt;

&lt;p&gt;Infrastructure as code, Git based workflows, monitoring, configuration management, immutable images, automated backups, and clear runbooks are what make this model realistic.&lt;/p&gt;

&lt;p&gt;Infrastructure knowledge is becoming valuable again&lt;/p&gt;

&lt;p&gt;For a while, some people believed developers would no longer need to understand infrastructure deeply. Managed platforms would hide the details.&lt;/p&gt;

&lt;p&gt;That prediction did not fully come true.&lt;/p&gt;

&lt;p&gt;Modern software still depends on networking, storage, Linux, DNS, TLS, routing, load balancing, databases, queues, observability, and security. When something breaks, abstraction is helpful only until it hides the root cause.&lt;/p&gt;

&lt;p&gt;The best engineers today are not just writing application code. They understand how their code behaves in production. They know what happens when latency increases, when disk IO is saturated, when DNS fails, when a certificate expires, when a region goes down, or when a deployment creates unexpected load.&lt;/p&gt;

&lt;p&gt;Infrastructure knowledge is no longer only for system administrators. It is becoming a core engineering skill again.&lt;/p&gt;

&lt;p&gt;The future is not cloud first. It is architecture first&lt;/p&gt;

&lt;p&gt;The next phase of infrastructure will not be defined by one platform.&lt;/p&gt;

&lt;p&gt;It will be defined by better decision making.&lt;/p&gt;

&lt;p&gt;Cloud is excellent for many things. Bare metal is excellent for many things. Edge is excellent for many things. Managed services, open source platforms, private clouds, and colocation all have a place.&lt;/p&gt;

&lt;p&gt;The mistake is choosing any of them automatically.&lt;/p&gt;

&lt;p&gt;The better approach is architecture first:&lt;/p&gt;

&lt;p&gt;Understand the workload.&lt;br&gt;
Understand the business constraints.&lt;br&gt;
Understand the cost model.&lt;br&gt;
Understand the security requirements.&lt;br&gt;
Understand the operational capacity of the team.&lt;br&gt;
Then choose the infrastructure that fits.&lt;/p&gt;

&lt;p&gt;This is a more mature way to build systems. It is also more honest.&lt;/p&gt;

&lt;p&gt;Infrastructure is not just a place where applications run. It is part of the product, part of the cost structure, part of the security model, and part of the user experience.&lt;/p&gt;

&lt;p&gt;The cloud era taught developers to move fast. The next era will teach them to choose wisely.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>BGP Edge Hygiene at a PCI-Regulated Fintech: IRR + RPKI in Production</title>
      <dc:creator>Berik Ashimov</dc:creator>
      <pubDate>Fri, 15 May 2026 17:23:20 +0000</pubDate>
      <link>https://dev.to/ashimov/bgp-edge-hygiene-at-a-pci-regulated-fintech-irr-rpki-in-production-3gm4</link>
      <guid>https://dev.to/ashimov/bgp-edge-hygiene-at-a-pci-regulated-fintech-irr-rpki-in-production-3gm4</guid>
      <description>&lt;p&gt;A single hijacked prefix can route a chunk of payment traffic into a stranger's network for half an hour before anyone notices. For a payment provider, that is not a routing incident. It is a regulatory event, an exposed-traffic incident, and an auditor knocking on Monday morning.&lt;/p&gt;

&lt;p&gt;This post walks through the BGP edge hygiene we ran in production at a national fintech: what we filtered, how we automated it, what broke, and a copy-paste checklist at the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The threat model in 200 words
&lt;/h2&gt;

&lt;p&gt;If you run a public-facing AS, the internet routing system trusts you and your peers to announce only what you should announce. That trust is not enforced by default. Five classes of problem will hurt you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Route hijacks&lt;/strong&gt; where a remote AS originates your prefix and pulls traffic away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route leaks&lt;/strong&gt; where a transit customer accidentally re-announces full tables to a peer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub-prefix hijacks&lt;/strong&gt;, more-specific announcements that win longest-prefix-match.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BGP optimizer leaks&lt;/strong&gt;, a known class of incident where a vendor box generates synthetic more-specifics and a misconfigured peer re-advertises them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static fat-fingers from your own ops team&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a payment provider the consequences are not just availability. They include confidentiality risk on traffic that touches the cardholder data environment, PCI DSS scope expansion, and customer trust damage that lasts longer than any outage.&lt;/p&gt;

&lt;p&gt;We treated the BGP edge as a perimeter control, not a routing function. That framing pulled the security team, the compliance team, and the network team into the same review cycle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five layers of edge hygiene
&lt;/h2&gt;

&lt;p&gt;We layered five filters on every external eBGP session. Each one alone is insufficient. Together they cut routing-related incidents to near zero over the year we measured.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: max-prefix per session
&lt;/h3&gt;

&lt;p&gt;The cheapest, most effective control. If a peer accidentally leaks full tables to us, we want to tear the session down, not crash the box.&lt;/p&gt;

&lt;p&gt;Cisco IOS-XR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cisco_ios"&gt;&lt;code&gt;&lt;span class="kt"&gt;router bgp&lt;/span&gt;&lt;span class="nf"&gt; 65000&lt;/span&gt;
&lt;span class="k"&gt; neighbor&lt;/span&gt; &lt;span class="m"&gt;203.0.113.1&lt;/span&gt;
&lt;span class="k"&gt;  remote-as&lt;/span&gt; 64500
&lt;span class="k"&gt;  address-family&lt;/span&gt; ipv4 unicast
&lt;span class="k"&gt;   maximum-prefix&lt;/span&gt; 5000 80 restart 5
&lt;span class="k"&gt;  !&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Junos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;protocols&lt;/span&gt; {
    &lt;span class="n"&gt;bgp&lt;/span&gt; {
        &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="n"&gt;EBGP&lt;/span&gt;-&lt;span class="n"&gt;PEERS&lt;/span&gt; {
            &lt;span class="n"&gt;neighbor&lt;/span&gt; &lt;span class="m"&gt;203&lt;/span&gt;.&lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;113&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt; {
                &lt;span class="n"&gt;family&lt;/span&gt; &lt;span class="n"&gt;inet&lt;/span&gt; {
                    &lt;span class="n"&gt;unicast&lt;/span&gt; {
                        &lt;span class="n"&gt;prefix&lt;/span&gt;-&lt;span class="n"&gt;limit&lt;/span&gt; {
                            &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;;
                            &lt;span class="n"&gt;teardown&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt; &lt;span class="n"&gt;idle&lt;/span&gt;-&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;;
                        }
                    }
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 80% warning threshold is the important part. You want a syslog message before you go down, not after.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2: AS-path filters
&lt;/h3&gt;

&lt;p&gt;Reject any prefix whose AS-path contains your own ASN. This catches the surprisingly common case where a peer somewhere has a stale route through your AS and tries to send it back to you.&lt;/p&gt;

&lt;p&gt;Junos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;policy&lt;/span&gt;-&lt;span class="n"&gt;options&lt;/span&gt; {
    &lt;span class="n"&gt;as&lt;/span&gt;-&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="n"&gt;OWN&lt;/span&gt;-&lt;span class="n"&gt;AS&lt;/span&gt;-&lt;span class="n"&gt;IN&lt;/span&gt;-&lt;span class="n"&gt;PATH&lt;/span&gt; &lt;span class="s2"&gt;".* 65000 .*"&lt;/span&gt;;
    &lt;span class="n"&gt;policy&lt;/span&gt;-&lt;span class="n"&gt;statement&lt;/span&gt; &lt;span class="n"&gt;DENY&lt;/span&gt;-&lt;span class="n"&gt;OWN&lt;/span&gt;-&lt;span class="n"&gt;AS&lt;/span&gt; {
        &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt;-&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="n"&gt;OWN&lt;/span&gt;-&lt;span class="n"&gt;AS&lt;/span&gt;-&lt;span class="n"&gt;IN&lt;/span&gt;-&lt;span class="n"&gt;PATH&lt;/span&gt;;
        &lt;span class="n"&gt;then&lt;/span&gt; &lt;span class="n"&gt;reject&lt;/span&gt;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also reject paths containing private ASNs (64512 to 65534 and 4200000000 to 4294967294) on peering sessions where they have no business appearing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3: IRR-based prefix filters
&lt;/h3&gt;

&lt;p&gt;For every peer that is not a Tier 1 transit, build a per-peer prefix filter from their published &lt;code&gt;as-set&lt;/code&gt; in IRR. If a prefix is not in their published origin set, drop it.&lt;/p&gt;

&lt;p&gt;Generate with &lt;code&gt;bgpq4&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bgpq4 &lt;span class="nt"&gt;-h&lt;/span&gt; whois.radb.net &lt;span class="nt"&gt;-4&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; PEER-EXAMPLE-IN AS-EXAMPLE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This produces a prefix-list ready to paste into Cisco IOS-XR or Junos config. Pin to a specific IRR source (RADb, RIPE, ARIN) per peer to avoid junk from less-trusted databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 4: RPKI Route Origin Validation
&lt;/h3&gt;

&lt;p&gt;RPKI ROV is the only one of these five layers that gives you cryptographic origin authentication. Configure a local validator (Routinator, rpki-client, or OctoRPKI), feed it to the routers, and drop &lt;code&gt;invalid&lt;/code&gt; at the edge.&lt;/p&gt;

&lt;p&gt;Cisco IOS-XR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cisco_ios"&gt;&lt;code&gt;&lt;span class="kt"&gt;router bgp&lt;/span&gt;&lt;span class="nf"&gt; 65000&lt;/span&gt;
&lt;span class="k"&gt; rpki&lt;/span&gt; server &lt;span class="m"&gt;192.0.2.10&lt;/span&gt;
&lt;span class="k"&gt;  transport&lt;/span&gt; tcp port 3323
&lt;span class="k"&gt;  refresh-time&lt;/span&gt; 600
&lt;span class="k"&gt; !&lt;/span&gt;
&lt;span class="k"&gt; address-family&lt;/span&gt; ipv4 unicast
&lt;span class="k"&gt;  bgp&lt;/span&gt; bestpath origin-as use validity
&lt;span class="k"&gt; !&lt;/span&gt;

&lt;span class="k"&gt;route-policy&lt;/span&gt; RPKI-DROP-INVALID
&lt;span class="k"&gt;  if&lt;/span&gt; validation-state is invalid then
&lt;span class="k"&gt;    drop&lt;/span&gt;
&lt;span class="k"&gt;  else&lt;/span&gt;
&lt;span class="k"&gt;    pass&lt;/span&gt;
&lt;span class="k"&gt;  endif&lt;/span&gt;
&lt;span class="k"&gt;end-policy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the policy &lt;code&gt;in&lt;/code&gt; on every eBGP session. Do not "prefer valid", drop invalid. Halfway measures here are how partial hijacks slip through.&lt;/p&gt;

&lt;p&gt;Run at least two validators. We ran three (Routinator + rpki-client + a vendor appliance) and reconciled them in monitoring. If one validator goes stale, you do not want it silently flipping prefixes to NotFound.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 5: bogons, reserved, and martians
&lt;/h3&gt;

&lt;p&gt;Drop RFC1918, RFC6598 (100.64.0.0/10), documentation prefixes (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24), default route (unless you genuinely accept it), and anything with a prefix length above your accepted maximum (typically /24 for IPv4 and /48 for IPv6).&lt;/p&gt;

&lt;p&gt;This catches misconfigurations from your peers more often than malice. It is also what auditors look for in PCI DSS section 1 reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating it with Ansible
&lt;/h2&gt;

&lt;p&gt;Manual prefix-list updates do not scale past a handful of peers and they rot fast. IRR data changes daily. We built a small Ansible role that does the boring part.&lt;/p&gt;

&lt;p&gt;Pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pull each peer's &lt;code&gt;as-set&lt;/code&gt; from RADb or RIPE using &lt;code&gt;bgpq4&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Render the per-peer prefix-list with a Jinja2 template.&lt;/li&gt;
&lt;li&gt;Diff against the running config. If the delta exceeds a threshold (say, plus or minus 10%), flag for human review instead of pushing.&lt;/li&gt;
&lt;li&gt;Push via Netmiko or NAPALM, with &lt;code&gt;commit confirm&lt;/code&gt; rollback on Junos and a &lt;code&gt;commit replace&lt;/code&gt; with diff preview on IOS-XR.&lt;/li&gt;
&lt;li&gt;Re-run nightly via cron. IRR data drifts continuously.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Minimal Ansible task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate prefix-list for peer&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;bgpq4 -h whois.radb.net -4 -A&lt;/span&gt;
    &lt;span class="s"&gt;-l "{{ peer.name }}-IN"&lt;/span&gt;
    &lt;span class="s"&gt;{{ peer.as_set }}&lt;/span&gt;
  &lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prefix_list&lt;/span&gt;
  &lt;span class="na"&gt;changed_when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Render config snippet&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peer_filter.j2&lt;/span&gt;
    &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/network-configs/{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;peer.name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.conf"&lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;prefix_list_body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;prefix_list.stdout&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sanity check delta&lt;/span&gt;
  &lt;span class="na"&gt;ansible.builtin.script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/diff_check.py "{{ peer.name }}.conf"&lt;/span&gt;
  &lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delta&lt;/span&gt;
  &lt;span class="na"&gt;failed_when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delta.rc not in [0, 2]&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Apply config&lt;/span&gt;
  &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delta.rc == &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="na"&gt;junipernetworks.junos.junos_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/network-configs/{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;peer.name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.conf"&lt;/span&gt;
    &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto-update&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;prefix-list&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;peer.name&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
    &lt;span class="na"&gt;confirm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;confirm: 5&lt;/code&gt; on Junos is the safety net. If the commit breaks the session and you cannot re-commit within 5 minutes, the box rolls back automatically.&lt;/p&gt;

&lt;p&gt;Store every generated config in git. When something goes sideways at 03:00, you want to see what changed in the last 24 hours, not guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things production taught us
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lesson 1: max-prefix saves you from your peers
&lt;/h3&gt;

&lt;p&gt;A regional peer added a new aggregate to their &lt;code&gt;as-set&lt;/code&gt; in IRR. Our nightly job picked it up and added it to the filter. The following morning their upstream withdrew the route entirely. Our session would have accepted the larger filter and idled around the new boundary. The 80% warning threshold on max-prefix fired an alert hours before the session reached the actual limit. We caught the IRR drift before anyone noticed at the routing layer.&lt;/p&gt;

&lt;p&gt;The lesson: IRR data is necessary but not authoritative. Always wrap it in a max-prefix that reflects the peer's actual size plus some headroom, not their theoretical max.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson 2: "prefer valid" is not "drop invalid"
&lt;/h3&gt;

&lt;p&gt;Early in the rollout we configured RPKI to prefer valid over invalid rather than dropping invalid outright. The reasoning seemed sound at the time: do not break things on day one.&lt;/p&gt;

&lt;p&gt;Then a partial hijack happened. A misconfigured AS announced an invalid origin for a /24 that overlapped a covered /22. "Prefer valid" picked the valid /22, but the more-specific /24 still won longest-prefix match because no valid /24 existed in the BGP table. Traffic for that /24 went to the hijacker for about 12 minutes.&lt;/p&gt;

&lt;p&gt;We flipped to drop-invalid on every session that night. We lost a small handful of legitimate prefixes whose ROAs were misconfigured by their owners. We sent them email. They fixed it. Net incident count went down, not up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesson 3: pre-commit diff validation catches typos
&lt;/h3&gt;

&lt;p&gt;An AS-path regex update almost dropped a legitimate transit prefix because the regex matched too aggressively. The Ansible diff-check script flagged a delta of minus 1,200 prefixes against the previous run. We caught it before push.&lt;/p&gt;

&lt;p&gt;If your automation does not have a "this change looks too big, ask a human" gate, build one. The cost is one extra step per change. The benefit is not paging your team at 02:00 because a regex ate the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this maps to PCI DSS
&lt;/h2&gt;

&lt;p&gt;If you operate in a PCI environment, the BGP edge is in scope, even if you sometimes argue otherwise. The relevant controls map cleanly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Requirement 1.2 (network segmentation):&lt;/strong&gt; A clean edge defines your perimeter. RPKI drop-invalid is the cleanest possible argument that you only accept authenticated origins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requirement 10 (logging):&lt;/strong&gt; Every RPKI validation state transition, every max-prefix warning, and every prefix-list change must reach your SIEM. Auditors will ask.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requirement 11.4 (intrusion detection):&lt;/strong&gt; Anomalous prefix-count deltas, sudden session flaps, and unexpected origin AS changes are network IDS signals. Wire them to alerting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requirement 6.4 (change management):&lt;/strong&gt; Git-backed configs, pre-commit diff validation, and commit-confirm rollback are change management. Show the auditor the commit log and the rollback playbook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Done right, network hygiene becomes compliance-by-design, not a separate workstream.&lt;/p&gt;

&lt;h2&gt;
  
  
  The take-home checklist
&lt;/h2&gt;

&lt;p&gt;If you are setting this up in your own environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] max-prefix per eBGP session, with 80% warning threshold
[ ] AS-path filter rejecting your own ASN in the path
[ ] AS-path filter rejecting private ASNs on public sessions
[ ] IRR prefix filter per non-transit peer, regenerated daily
[ ] RPKI ROV with drop-invalid (not prefer-valid)
[ ] At least two RPKI validators, reconciled in monitoring
[ ] Bogon and reserved prefix drops at the edge
[ ] Maximum prefix length filter (typically /24 v4, /48 v6)
[ ] Pre-commit diff validation with a "too big" abort
[ ] commit-confirm or equivalent rollback on push
[ ] Git-backed configs with audit log
[ ] Logging RPKI state transitions to SIEM
[ ] Alerting on prefix-count delta over 10 percent
[ ] Quarterly review of every peer as-set
[ ] Runbook for sudden BGP session flap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you implement the first six items, you have removed the largest sources of BGP edge risk for your AS. Everything else is operational polish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final note
&lt;/h2&gt;

&lt;p&gt;None of this is novel work. IRR has been around since the 1990s, RPKI since the early 2010s. What is novel is that for most payment providers, fintechs, and regulated networks, this is still not the default configuration. The gap between "everyone should be doing this" and "everyone is doing this" is where edge incidents come from.&lt;/p&gt;

&lt;p&gt;If your AS is announced on the public internet and you cannot tick off most of the checklist above, you have homework.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write about production network reliability, BGP edge security, and infrastructure automation. Find me on &lt;a href="https://www.linkedin.com/in/berik-ashimov" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or reach out at &lt;a href="mailto:berik@ashimov.com"&gt;berik@ashimov.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>devops</category>
      <category>security</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
