
Megaport Connect Cloud Networking Summit
A first-of-its-kind virtual summit built to help network engineers and IT leaders upskill, share ideas, and connect around the future of cloud and hybrid networking

The Full Stack Network: From Multi-Cloud to Bare Metal (And Everything We Broke Along the Way)

Richard Olson
Tech Lead (Networking and Compute), Canva
Richard has spent the past four years growing Canva's network from a single cloud region to a global, multi-cloud fabric spanning hyperscalers, neoclouds, and data centres. He has twenty years in networking, is a self-confessed automation hipster, and got his start in IT throwing rocks into trees.
The Full Stack Network: From Multi-Cloud to Bare Metal (And Everything We Broke Along the Way) – Key Takeaways
Overview
Richard Olson, Tech Lead (Networking and Compute) at Canva, explains how Canva’s network grew from a loose collection of AWS VPCs into a global multi-cloud environment spanning hyperscalers, neoclouds, and bare metal. Olson has about twenty years of networking experience. He started in the military, building temporary field telephone networks, then moved through network operations and design roles, taught himself to code, and worked at a large cloud company before joining Canva.
The session follows the network’s evolution in order: a single-cloud, single-region foundation, then multi-region, multi-cloud, and finally neoclouds and bare-metal GPU capacity, covering integration patterns, lessons learned when things broke, and three cost engineering techniques. One piece of context shapes everything: Canva is 99.9% cloud-based, with the remaining 0.1% being office internet. The team operates no physical network infrastructure, so vendor routers and switches were never part of its toolkit.
The central theme is that network complexity has an ongoing cost, even when it looks free on day one. Every design choice comes with trade-offs that eventually surface in operations, routing behavior, or the bill.
1. From a Loose Collection of VPCs to a Real Network
In Canva’s early cloud years, everything important lived in production, and the network was less a network than a loose collection of VPCs and subnets that did not need to talk to each other. As the company grew, the VPC count exploded, from 20 VPCs in 2019 to 200 in 2022, tripling in 2021 alone. Where back-end services did need to communicate across VPCs, teams used ad hoc VPC peering.
Olson joined as one of Canva’s first three cloud networking engineers, with a simple mandate: build a network. An early priority was centralizing internet egress for back-end services. Canva had hundreds of NAT gateways, most in VPCs that were not even using them, and each carried an hourly availability cost.
The team rolled out a standard AWS Transit Gateway architecture, with development and staging VPCs on a non-production transit gateway and production VPCs on a production transit gateway. This created a promotion path: infrastructure-as-code changes were tested in non-production before reaching production. Canva then built a centralized NAT gateway capability, shut down hundreds of NAT gateways for a significant cost saving, and later evolved the design into a centralized firewall capability. Just as that network was built, though, Canva needed to replace it: after a decade in a single region, the company had to expand globally.
2. AWS Cloud WAN and the Platform Layer
Going global exposed two lessons. First, start with a unique addressing plan rather than using 10.0.0.0/16 everywhere because the documentation says so. Canva’s combined development and staging network and its production network both used 10.0.0.0 addressing, and untangling that meant shuffling databases and adding extra prefixes. Second, transit gateways are regional resources, so peering them between regions relies on static routes, a painful prospect across a messy IP schema.
Around 2023, roughly a year after AWS Cloud WAN became generally available, Canva adopted it for three capabilities: an any-to-any mesh defined in a declarative JSON policy, where adding a region means appending it to a list; dynamic routing, which Olson calls the big one; and segment sharing, which controls which segments can reach each other. The result has been boring in a good way: only 20 configuration changes since deployment in 2023, mostly adding or removing segments or regions. Canva runs two Cloud WAN core networks, one for production and one for non-production, across six to eight global regions.
Some services, such as secrets management, infrastructure-as-code tooling, and CI build runners, had to touch infrastructure in both production and non-production, so Canva coined the term platform for them. Because Cloud WANs cannot be connected natively, Canva uses Transit Gateway between them. Before AWS added routing policies, a special filtering segment with no VPCs attached let Canva share only select VPCs across environments rather than all of production.
That design carries its own lesson: when connecting Cloud WANs through transit gateways, put a transit gateway in every connected region. Otherwise, traffic from a non-production VPC in ap-southeast-2 (Sydney) may take a path AWS documentation describes as deterministically random, potentially reaching the United States via Europe. A local transit gateway keeps the crossing between environments local, with optimal routing beyond it.
3. Segmentation Has an Ongoing Cost
On top of the production and non-production routing domains, Canva overlaid “functions” such as platform, supply chain, source control, general purpose, build, isolated, and CI, each a separate Cloud WAN segment. Internal customers would ask where to deploy workloads that needed to reach particular services, and eventually no one knew where to deploy anything, while workloads often could not communicate anyway. At one stage there were about 15 different combinations.
Each new segment felt like good security hygiene at the time, but each added routing policy, attachment rules, and one more thing to think about at 2 a.m. during an incident. Canva flattened the design, moving regular workloads into the fabric segment while keeping the platform segment for the services that bridge production and non-production.
Flattening did not result in a loss of security. Segments, like VRFs, separate traffic effectively, but here they were a coarse control with significant operational overhead and workarounds. Olson frames the lesson as complexity being pushed to the application layer, and notes that network complexity carries an ongoing cost even when it appears free on day one.
4. The First Multi-Cloud Link
Around 2023, with Canva in about three AWS regions, Google Cloud arrived as a second cloud. Canva needed high-speed connectivity well beyond the roughly 1 to 1.5 Gbps of a VPN tunnel, without running dozens of tunnels, and expected to move a lot of data, which is expensive over the internet. In mid-2023 it chose Google Cloud Cross-Cloud Interconnect, which pairs AWS Direct Connect with Google Cloud Interconnect, with Google arranging the cross connects rather than Canva handling a letter of authorization. The product was new, about two years ahead of the more recent multi-cloud interconnect offerings, and it fit: only one region in each cloud, both in Northern Virginia, needed connecting, throughput needs were high, and Direct Connect data transfer was substantially cheaper. The catch was that a point-to-point product would eventually need replacing.
Extending segmentation across clouds was harder. The link ran directly from a Direct Connect gateway to a Google Cloud Router, limiting Canva to hyperscaler features: no BGP communities, no route maps, and only light control over summary routes. Canva built a mesh of virtual interfaces (VIFs), or VLANs in some providers’ terminology. Production to production was simple, but everything on the Google Cloud side needed platform services, so a dedicated platform Direct Connect gateway connected to each Cloud Router through a pair of redundant VIFs.
DNS added a wrinkle. Amazon Route 53 was Canva’s authoritative private DNS, and Google Cloud forwarding zones let Google Cloud resources consume it, but forwarded queries are sourced from a public address range. That effectively created another overlapping range that had to be advertised across multiple segments. Canva carefully limited propagation to build to build, non-production to non-production, and production to production, so responses returned to where requests originated.
5. Network-as-a-Service Providers Became the Hub
With Google Cloud in a single metro next to an AWS region, point-to-point connectivity delivered optimal latency and routing. But Canva had gone multi-region and multi-cloud in a single year, and any additional cloud or region raised the classic full mesh versus hub-and-spoke problem. Three regions need three links; Olson’s example of eight clouds and regions needs about 56 redundant links in a full mesh.
In 2024, Canva pivoted to network-as-a-service (NaaS) providers. At the time, the newer multi-cloud interconnect initiatives had not been announced, and beyond a handful of services such as Cross-Cloud Interconnect, there were no real private connectivity alternatives. Instead of AWS in the primary region acting as the hub, or a full mesh, the NaaS providers became the hub and every cloud a spoke, supporting any number of clouds and regions with any-to-any connectivity.
Today, Canva uses multiple interconnected NaaS providers with complementary capabilities: global coverage, physical ports, virtual routers, internet services, and multiple jurisdictions. The network spans more than half a dozen clouds and between 15 and 20 regions, depending on current requirements.
6. Neoclouds and the Routable Pod Problem
Until 2024, the network’s growth had been fairly orderly. Then GPUs and bare metal arrived. Canva needed to connect wherever GPU capacity was available, increasingly meaning neoclouds, most of which offer bare metal and lack a decade or two of experience operating high-scale virtualization platforms. Every neocloud integration is completely different.
Kubernetes is Canva’s universal compute platform, and early on Canva chose routable pods, the default pattern on both hyperscalers it uses. Each node, a virtual or bare-metal machine running the kubelet, hosts dozens or hundreds of pods, each with a unique IP address from the container network interface (CNI). Routable pods mean the network knows every pod and its node.
On AWS, the AWS CNI or Cilium in ENI mode calls the AWS API to request an address or a prefix such as a /28 or /80, and the hypervisor knows that the prefix lives on a particular NIC and how to route to it. On bare metal, those primitives do not exist, so each neocloud had to be integrated at both the node and Kubernetes layers.
7. Four Neocloud Integration Patterns
Olson describes four providers, each named for what Canva had to bring:
- Bring a router. Provider A offered a layer 2 domain and multi-NIC virtual machines but no routing. Canva runs a virtual router that provides a VRRP first-hop gateway and dynamic BGP to the nodes, so the network learns which node holds which pod prefix; because nodes come and go constantly, static BGP neighbors would turn a couple of node reboots into a hundred alerts. Fiber interconnects were hard to get in that provider’s regions, so the router connects home over the internet, putting a Canva-operated VM in the critical path, subject to throughput limits and the internet underlay.
- Bring everything. Provider B accepted fiber but offered no virtual machines, heavily capped internet access, and no routing. Canva provides VRRP, DHCP, and dynamic BGP, effectively running a small data center network on someone else’s layer 2 while the vendor handles cabling. For a team with no on-premises infrastructure, this was foreign, and it had to be done in days, not months.
- Bring a Kubernetes controller. Provider C looked easiest on paper: a proper cloud with real VPCs and provider-owned route tables. But it had no integration with Canva’s CNI, offering pod routing only through its own managed Kubernetes, and with no layer 2 Canva could not drop in a router. Rather than adopt that Kubernetes and diverge from the tooling built around its own platform, Canva wrote a controller that calls the provider’s API to update the route table with which /26 pod prefix lives on which node.
- Just bring yourself. Provider D is by far the easiest and serves as Canva’s benchmark: a pair of high-speed fiber interconnects and redundant BGP sessions, with the provider aggregating node and pod routes and taking DHCP and VRRP off the table. People at the provider assisted with the integration, allowing flexibility that strict hyperscaler guardrails and quotas would not. When a provider gets this right, the network team barely notices it.
Performance testing proved critical. Hyperscaler network rate limits are well documented, but some neoclouds impose aggressive limits, and some Canva VMs could not exceed one or two gigabits per second when far more was needed.
Together, the patterns form a U-curve of complexity: a more capable cloud can be harder to integrate than a simpler one. The layer 2 patterns are relatively easy, while the Kubernetes controller sits at the bottom of the curve because it required a full software package, not just network integration. Providers that own everything, including the hyperscalers, sit at the easy end.
8. Hidden Assumptions Outside the Hyperscalers
Several obscure issues surfaced across neocloud deployments:
- Distributed computing fallacies. Canva grew up in one cloud and one region, and data has gravity: it is hard and expensive to move and costly to store at volume. When workloads land wherever GPUs are available, application teams must accept that latency is not zero and bandwidth is not infinite.
- Default settings. Providers may ship default builds and images with surprising behavior. In one case, a default ARP setting suppressed replies for pods because a hyperscaler had effectively disabled internal ARP on the virtual machine. Canva also hit ARP table limits in one cloud.
- IPv6. Kubernetes consumes IP addresses rapidly, and IPv6 is the answer for routable pods at scale, yet full IPv6 support remains rare even in 2026.
- Storage versus transfer. Storing a gigabyte for a month often costs about the same as downloading it once. If data must be downloaded twice, replicating it and then reading it without further transfer charges may make more sense.
9. Cost Engineering: Egress Firewalls on NaaS Routers
The first cost tip builds on the NaaS pivot: with NaaS virtual routers and internet access already providing ubiquitous inter-cloud connectivity, Canva placed firewalls on those routers. That removes managed NAT gateway and cloud-native firewall processing fees, gives every cloud the same standard egress deployment instead of a proprietary one per provider, and extends Canva’s egress controls to neoclouds that have no native firewalling.
Olson illustrates the economics with a hypothetical 1 PB transferred in each direction. Ingress is typically free, but processing fees of around 6.5 cents per GB make the download $65,000. The upload adds data transfer out to the firewall processing fees, for about $115,000, or roughly $180,000 in total. With fixed-rate transfer through a NaaS provider, uploads might incur only Direct Connect fees, and downloads remain free on Direct Connect ingress. Consumption-based and fixed-rate billing always have a break-even point, so each organization must model its own traffic patterns, but beyond that point, outsourcing egress is clearly worthwhile.
Citing Russ White, Olson notes that if the trade-offs are not visible, the search has not gone deep enough. Here there are two:
- Capacity management. As in on-premises networking, Canva now owns capacity. An elastic workload that bursts from zero to 100 Gbps for an hour a day must either be sized for peak, leaving capacity unused for 23 hours, or accept slower performance, such as a one-hour job taking four hours.
- Reliability. Cloud-native firewalls are engineered for resilience to failure scenarios. With self-managed firewalls, placing endpoints in three availability zones no longer takes care of it, and Canva is on the hook if a firewall fails.
One approach Canva experimented with is a fail-open design. A pair of IPv4 /1 routes, together covering the entire internet, is advertised dynamically into the VPC over BGP on Direct Connect, while the static 0.0.0.0/0 route stays in place. If both firewalls and routers at a metro’s point of presence fail, the /1 routes are withdrawn and the static default route sends traffic to the cloud-native path.
10. Cost Engineering: VPC Peering, Private VIFs, and Route Quotas
The second tip favors pragmatism over perfect design. Cloud WAN still provides universal connectivity, but VPCs that exchange heavy traffic, such as compute VPCs that Canva scales horizontally to limit blast radius and the resource VPC they share, use VPC peering. Peering is free within an availability zone and 1 cent in each direction across zones, while Cloud WAN, Transit Gateway, or Google Cloud’s Network Connectivity Center (NCC) typically charge about 2 cents per GB. Setting aside application-layer optimizations such as topology-aware routing, which Olson concedes are probably the better answer, sending 1 PB from one availability zone to itself and two others costs about $60,000 through Transit Gateway or Cloud WAN versus $40,000 with peering, a one-third saving. A uniform hub-and-spoke design is cleaner, but here cost-effectiveness won out over simplicity.
The third tip applies the same idea to hybrid connectivity: where possible, use private VIFs into Direct Connect gateways rather than transit VIFs, bypassing Cloud WAN or Transit Gateway so inter-cloud traffic avoids the 2-cent processing fee. Canva runs a Direct Connect gateway per point of presence, one per segment, for fine-grained routing control. The trade-off is more gateways to operate, but as a software company managing everything as infrastructure as code, Canva finds the scale trivial: by Olson’s understanding of the quotas, up to 50 private VIFs with up to 20 VPCs each allows about a thousand VPCs per region. In his comparison, saving 2 cents per GB on every petabyte transferred adds up to roughly a top-of-rack switch.
Private VIFs also exposed a quota trap. VIFs typically allowed 100 routes per BGP session, although quota management has recently changed, and a 101st route dropped the session. Canva had the quota raised, then hit a second limit: the VPC still accepted only 100 propagated routes, so route 101 was silently ignored by the VPC route tables. In one region the state got stuck and required a support ticket even after routes were withdrawn. With AWS still capped at 100, the fix was aggressive per-region summarization into the hyperscalers plus a simple static route in Terraform pointing back to Cloud WAN, rather than advertising a 10.0.0.0/8 from Direct Connect with more specific regional routes in the VPC.
Key Takeaways
- Start with a unique addressing plan. Overlapping 10.0.0.0 addressing across environments cost Canva significant time shuffling databases and adding prefixes.
- Dynamic routing and declarative policy reduce churn. Canva’s Cloud WAN deployment has needed only 20 configuration changes since 2023.
- Network complexity has an ongoing cost, and the wrong complexity does not scale. Each extra segment added routing policy, attachment rules, and incident-time load, so Canva flattened its segments.
- Point-to-point links do not scale with clouds and regions. Making NaaS providers the hub lets Canva add clouds and regions as spokes with any-to-any connectivity.
- Every neocloud integration is different. Depending on the provider, Canva has brought a router, a small data center network, a custom Kubernetes controller, or simply itself.
- A more capable cloud can be harder to integrate. The provider with real VPCs but no CNI integration required the most custom work: a Kubernetes controller.
- Performance testing is critical outside the hyperscalers. Some neocloud VMs could not exceed one or two gigabits per second.
- Cost optimizations shift responsibility to the network team. Egress on NaaS routers means owning capacity and firewall reliability, and private VIFs mean more gateways and route quotas to manage.
- Greater control brings greater operational overhead. That load lands on code, observability, or additional engineers, so cloud savings should be weighed against how many engineers they could fund.
- Know the cost per gigabyte for every path. Olson calls this tricky, but each cost saving described depends on understanding what a traffic path costs.
Conclusion
Canva’s network story shows how quickly cloud networking requirements can change. In a few years, the team moved from a loose collection of VPCs to transit gateways, Cloud WAN, a second cloud, NaaS providers as the hub for more than half a dozen clouds, and finally neoclouds that required everything from a virtual router to custom Kubernetes software. Each stage solved the immediate problem while setting up the next redesign.
The recurring lesson is that complexity is never free. Extra segments and point-to-point links looked reasonable at the time but had to be unwound, and the cost optimizations brought new operational responsibilities. Olson’s closing advice reflects that: the wrong complexity does not scale, more control means more overhead, and teams need to know the cost of every path their traffic takes.
For cloud-only network teams, the session offers a practical model: prefer dynamic routing and declarative policy, keep segmentation simple, test neocloud performance, and treat cost engineering as a design discipline with its own trade-offs.
The Full Stack Network: From Multi-Cloud to Bare Metal (And Everything We Broke Along the Way) – Full Transcript
Host: It’s one thing to talk about architecture in theory, but it’s another thing entirely to build and operate these environments in the real world, which brings us to our next speaker. Richard Olson is the tech lead for networking and compute at Canva, and he’s helped grow their network from a couple of VPCs into a global multi-cloud environment spanning hyperscalers, neoclouds, and bare metal. Richard has spent about 20 years working in networking and describes himself as a bit of a network automation hipster. Today, he’s going to share some of the architecture decisions, trade-offs, and the things that broke along the way at Canva as they scaled their architecture. So please welcome Richard.
Richard Olson: Thank you so much, Alexis, and thank you, everyone, for having me. Good morning, good afternoon, good evening, depending on where you’re coming from. And I just want to say a special thank you to Chicago for the weather. It is exactly what the weather is back in my hometown.
And speaking of my hometown, I’m from a little town that some of you may not have heard of called Canberra. In Australia, a little over 100 years ago, Sydney and Melbourne were arguing about who should be the capital city, and they couldn’t agree. So what they did is they drew a straight line from Sydney down to Melbourne, they found the spot with the most kangaroos, and they called that Canberra, which means meeting place. And so it’s pretty much your Washington, DC, but populated by marsupials and venomous snakes. And that’s where I live.
All right. Who am I? I started life in technology a little bit differently to most folks. I was throwing rocks into trees. I was literally getting a bit of field cable, finding a good-sized rock, taping it up with some electrical tape, and then hurling that into the bough of a nearby tree, because I was in the military. And when you’re in the bush in the middle of nowhere and your boss wants to talk to his boss, you don’t have a phone network. So I was the guy out in the middle of nowhere who would build that phone network in a day, rip it down the next day, move, and there we are.
From there, I left the military and followed, I would say, a fairly standard career trajectory in networking: a bit of level 2 NOC, level 3 design. And I taught myself to code along the way, which was cool. And then I started to get into cloud. I actually worked for a big cloud company. But when I was at that cloud company, surrounded by all of this cutting-edge technology, super cool, I just felt that I wanted to go back to my roots. There was this little voice inside of me saying, you love networking.
I was a foolish teenager. I actually bought an ATM switch on eBay. Had no idea what it did. It was $200. It was the worst $200 I ever spent when I was a teenager, but clearly something said networking. And so, about five years ago, I saw a job pop up at Canva, and it was cloud networking. So here were two of the things: the one I was doing, which I like, and the one that I love and have always done. And so that’s how I wound up at Canva.
For those that don’t know Canva, Canva is a global online visual communication platform designed to empower the world to design. It’s a simple way to create beautiful designs. And what that means for folks in the room, network engineers and architects, is you have infinite whiteboards, and you can draw awesome network diagrams. And I’m going to show you a few of those today. So Canva supports the end-to-end visual communication process, which is really cool.
All right. We’ve got a fair bit of content to cover today, and I’m going to dive in in a second. We’re going to start from the beginning, with a single-cloud foundation, one region, one cloud, and we’re going to grow that into multi-region. And then we’re going to head over to multi-cloud and neocloud. And I’m going to talk about some of the integration patterns that we’ve used, some of the lessons we’ve learned, and, hopefully of interest, some of the ways we’ve learned to apply some cost efficiency.
Now, just to add a small disclaimer to some of the things that I do and the way that I talk. Unlike a lot of the networks that some of you folks might be managing, Canva is 99.9% cloud-based, and that 0.1% is office internet. So some of the solutions which you’ve got available to you, your routers from your favorite vendor, your switches, I didn’t have those. We are operating zero physical infrastructure from that perspective.
All right. So our story begins. Back then, everything important lived in prod, and there wasn’t really a network so much as a loose collection of VPCs and subnets which didn’t need to talk to each other. But then, as the company grew, the VPC count exploded and nothing could communicate. When I joined Canva around June 2022, I was one of the first three cloud networking engineers, and our mandate was simple: build a network.
I mentioned the rate of growth was huge back then, and we’re talking network growth here. We had 20 VPCs in 2019, and that exploded to 200 in 2022. It tripled in 2021 alone. And at the time, some of these VPCs had started to communicate between back-end services, and we were using a mix of ad hoc VPC peering where teams needed that inter-VPC connectivity.
But one of the first things that we wanted to do as the networking team: we had an egress capability going from a back-end service out to the internet, and we wanted to centralize that capability. And we also had hundreds and hundreds of NAT gateways. Most of these VPCs weren’t even using these NAT gateways, and as some of you folks may know, NAT gateways have an hourly availability cost, and that’s something that we wanted to reduce.
So what we did, we rolled out transit gateways, pretty standard architecture in Amazon. We grabbed all of our dev and staging VPCs and plopped them into what we called the non-production transit gateway, and all of our prod VPCs into the prod transit gateway. And what that gave us is a way to do code progression or promotions. It meant that when I was making a code change, I would test it on my non-prod transit gateway. This is the infrastructure as code that some folks have been talking about. And let’s say dev and staging went well, that would then be promoted up into prod and the change would be rolled out. Sensational.
And so we rolled out a centralized NAT gateway capability. We shut down hundreds and hundreds of NAT gateways. Big cost saving. Fantastic. And this then evolved into our centralized firewall capability. But just as we built this network, we actually needed to replace it, because after being in a single region for a decade, we needed to expand our footprint globally.
So there’s a bit of a lesson learned here. You might have got it from the last slide. Please start with a unique addressing plan. You don’t need to use 10.0.0.0/16 everywhere just because the docs say that. By folding our dev and staging together on one network, and our prod network also on 10.0.0.0, we spent a lot of time shuffling databases, adding extra prefixes, and that sort of stuff.
The next lesson that we learned: transit gateways are great for connectivity within a region, and they definitely have the capability to go between regions. But with transit gateway peering, transit gateways are a region-based resource. So if you’re peering between regions, you’re using static routes. And at the time, we had a really messy IP schema, so the idea of summarized static routes everywhere was quite a painful thought.
So we turned to Cloud WAN. This is circa 2023, and it was about 12 months earlier, I think, that AWS had announced the general availability of AWS Cloud WAN. And it brought several enhancements that we really needed. One of them, which is nice to have, is any-to-any mesh. We could easily achieve this with transit gateways plus infrastructure as code. But what Cloud WAN gave us was this nice declarative policy in JSON, and I could simply append a region to a list and magic would happen. Job done.
Dynamic routing, though, was the big one. I just touched on managing that list of static routes. Now, we could have done that with infrastructure as code, coming up with a recursive list and populating all of our VPCs everywhere. But as a lot of you are network engineers, I’m sure you know dynamic routing typically beats static routing nine out of 10 times when you’ve got that sort of an environment.
The last thing that Cloud WAN gave us that we really liked was segment sharing. For those that aren’t aware of segment sharing, in Cloud WAN you define segments which you attach VPCs to. You can see on the diagram I’ve got a fabric and a platform segment, for example. And then you can selectively say, hey, fabric can talk to platform, but it can’t talk to the isolated segment. And we really liked that, because it gave us a way to control this selective connectivity.
So, TL;DR, it was a no-brainer over a number of regional transit gateways using static routes. And it’s actually been really boring, in a good way. We’ve only made 20 configuration changes since we deployed that in 2023, and most of them are adding or removing segments or regions.
Inside AWS, just like the diagram shows, we actually run two Cloud WAN core networks, similar to the transit gateways I mentioned, one for prod and one for non-prod. We run this across somewhere between six and eight global regions, depending on where we are at the time. And having these two Cloud WANs, like I said before, still gives us that code promotion path, not that we’ve needed it, with 20 configuration changes over a couple of years.
But what we discovered during the Transit Gateway era, in the later days, was that we had a subset of services which needed to communicate with both production and non-production. We had this lovely separation, prod will never talk to non-prod, but we had services such as secrets management, infrastructure as code, and build CI runners, which would need to touch and mutate infrastructure across both environments and needed to talk to prod and non-prod. And that’s where we coined the term platform. To provide platform services connectivity between the Cloud WANs, we actually use Transit Gateway. Still to this day, you can’t natively connect Cloud WANs.
AWS has recently added routing policies, but at the time, as you can see on the diagram, we had a special filtering segment we called platform to non-prod, with no VPCs attached, which let us manipulate the routing policy before there was a routing policy. And so that meant that we’re not sharing all of prod to non-prod, just those select VPCs.
A fun lesson came from this connectivity using transit gateways. If you do connect multiple Cloud WANs, make sure you’ve got transit gateways in all of the regions where you connect these Cloud WANs. Otherwise, what happens is your packet that’s leaving your non-production VPC, say in ap-southeast-2, Sydney, good region there, if you don’t have this local transit gateway, is going to deterministically randomly, and that’s their documentation, select a path, probably through a suboptimal region. So that means if Australia needs to go to the US, unless you’ve got that local transit gateway which makes it cross to prod immediately, it may actually go via Europe to get to the US. So having a local transit gateway ensures that traffic crosses between prod and non-prod in the local region, and from there you have optimal routing to the remote region.
All right. I just mentioned segments, one of the nice things about Cloud WAN. You can tell from the title where I’m going here: the cost of complexity. So we created those two concepts. We called them routing domains, the prod and non-prod routing domains. And over the top of that, we overlaid what we called functions. There were functions like the one I’ve just mentioned, platform, but we had lots of functions: supply chain, source control, general purpose, build, isolated, CI. You can see where this is going.
These are all separate segments on that Cloud WAN. And what ended up actually happening is no one knew where to deploy anything. We use Kubernetes as our compute platform, which I’ll talk to a little bit more later. But a customer would come to us and say, where do I put my thing? I need to talk to this stuff. And in the end, no one knew where to deploy anything, and nothing could communicate anyway. We had about 15 different combinations at one stage.
So the lesson learned: every new segment felt like good security hygiene at the time, but each one added routing policy, attachment rules, and one more thing to think about at 2 AM during an incident. So we flattened things. We parked everything into the fabric segment, regular workloads and that sort of thing. The platform segment stayed, because that’s where those cross-domain prod to non-prod services stayed.
And this didn’t actually result in a loss of security. Some of you probably use VRFs, and you know that they are quite effective at separating things. It didn’t result in a loss of security, but that was quite a coarse control, and it had a lot of operational overhead and workarounds needed. And so this pushed the complexity to the application layer. That’s probably the lesson learned here. For us, network complexity has an ongoing cost, even when it looks free from day one.
All right. Now we’re entering the multi-cloud era. We’ve just gone multi-region. At the time, I think we were in three. This was about 2023. And a second cloud turned up. GCP arrived. And everyone at the time was talking about multi-cloud. I remember seeing all this media on LinkedIn, but then it was real. We were actually doing it. It wasn’t just talk.
And at the time, we had a requirement for high-speed internal connectivity. We’re talking more than your classic 1 to 1.5 gigabit that you can get on a VPN tunnel. I didn’t want to have dozens of VPN tunnels. And we were also going to be transferring a lot of data, and data transfer out via the internet is one of the most expensive ways as well. So a VPN service wouldn’t cut it. We ended up connecting using a service called GCP Cross-Cloud Interconnect.
There’s going to be a talk later by Will, who’s going to go in depth on things like Direct Connect and Cloud Interconnect. But essentially, the service is AWS Direct Connect on one side, GCP Interconnect on the other, and the Cross-Cloud Interconnect part comes in because GCP manages the cross connects. For anyone that’s done a cross connect in a data center, typically you get issued the LOA, letter of authority or authorization, and you need to arrange that yourself. But Google handled that for us.
And it worked. This was mid-2023. I think the product had just come out, and it was the obvious choice. This is approximately two years, I’d say, before the multi-cloud interconnect products started to come out. It was the obvious choice. We only needed to communicate between two regions, two clouds, in Northern Virginia. We needed that high throughput, like I said, and we wanted to maintain a reasonable price, and Direct Connect was substantially cheaper data transfer. But by building on a point-to-point connectivity product, we’d ultimately have to replace that.
More on that in a little bit, though, because remember that complexity that I mentioned before? Now we had a segmentation headache between clouds. You can see here we’ve got a few fewer segments. We started flattening these different things, but it got a bit tricky extending this between two clouds. Walking through the diagram, on the left we’ve got AWS, showing the Cloud WANs, their segments, the VPCs, and the VPCs connected to Direct Connect gateways. And on the right, we’ve got Google, with a classic hub-and-spoke VPC peering arrangement and some Cloud Routers.
The problem came because our first ever multi-cloud connection didn’t have fancy routers. We were constrained by the features that the hyperscalers gave us. This is a direct connection from a Direct Connect gateway to that Cloud Router. So we didn’t have communities, we didn’t have route maps, and we only had very light controls around summary routes.
To provide this connectivity between segments in a fashion similar to what we had on the AWS side, we ended up using a mesh of VIFs or VLANs, depending on your hyperscaler terminology. As the diagram shows, prod goes to prod. Simple. Where’s the problem? Well, we had those platform services, and everything on the GCP side needed to talk to those platform services. So what we did is we had a special platform Direct Connect gateway on one side, and it would have a pair of redundant VIFs to each of the Cloud Routers on the other side. And that meant that we provided that any-to-any connectivity for platform.
It was also tricky, what happened here. This provided the connectivity, but the next challenge we had was on the Google side. AWS Route 53 was our authoritative private DNS at the time, and we wanted GCP resources to be able to consume that private DNS. And GCP has forwarding zones. That’s pretty straightforward. The problem was that these forwarding zones are actually sourced from a public address range.
Don’t ask me to quote it right now. It’s 35-dot-something. But what that meant was, similar to the issues with the 10.0 private addressing back in the early VPC days, now we had effectively a duplicate overlapping range which had to be advertised across multiple segments. And in the end, what we had to do was just be super careful where we propagated that from. It would only go from build to build, non-prod to non-prod, prod to prod, and that way we ensured that the DNS response made it back to where the request came from. So this worked okay. Fortunately, we never had to consider both clouds having multiple regions and achieving that any-to-any connectivity until we had a little bit of time to think about it.
But as I mentioned just earlier, we ultimately had to change this. While GCP was in a single metro adjacent to an AWS region, having a point-to-point connection was workable. Latency and routing were optimal. But the question was always asked: we’ve just gone multi-region and multi-cloud in a single year, so what if we go to another cloud, another region? If I throw on another Google region, or another Amazon region, or another cloud, how are we going to make sure that we have that end-to-end connectivity?
So this basically created the classic networking problem of a full mesh versus a hub and spoke. The more regions you get, the more links. Three is a nice trade-off, three regions, three links, but then you get more links and more links. And so this diagram shows eight clouds and eight regions, and if I’m doing my mathematics correctly, this is about 56 redundant links for just eight regions, hub and spoke versus a full mesh.
So in 2024, we pivoted to a NaaS provider, or network-as-a-service provider. Back in 2024, as I mentioned just a moment ago, the more recent multi-cloud interconnect initiatives hadn’t been announced. So with the exception of a handful of services, like that Google Cross-Cloud Interconnect product I mentioned earlier, there weren’t really any other private connectivity options. So now, instead of AWS in our primary region being the hub with other clouds hanging off of it, or a full mesh, NaaS providers are the hub, and every cloud is just a spoke. We can roll out an arbitrary number of clouds and regions and provide that any-to-any connectivity that the network needs to provide.
So fast forward to today. This is a real diagram. Multiple interconnected NaaS providers give us complementary capabilities. We’ve got global coverage, fantastic, physical ports, virtual routers, internet services, multiple jurisdictions, more than about half a dozen clouds, and somewhere between 15 and 20 regions, depending on the current requirements.
All right. Then the next chapter. Up until 2024, this had all been fairly orderly. We went single cloud, single region, then multi-cloud and multi-region at the same time. And then GPUs and bare metal entered the picture. We needed to be able to connect to wherever the GPU capacity was, and that increasingly meant neoclouds. And most neocloud services offer bare metal. They don’t have a decade or two of experience operating high-scale virtualization platforms. So the problem every neocloud integration comes down to is that they’re all completely different.
We run Kubernetes, which provides us a universal compute platform. And early on in our Kubernetes journey, we opted to have routable pods. The hyperscalers that we use both defaulted to this pattern, and we’re 100% cloud, like I mentioned. So it just made sense.
And just to level set, I’m not going to deep dive into Kubernetes, but in Kubernetes, you have nodes. This could be a virtual machine or a bare metal machine running the kubelet, which phones home, and just like all servers, they’ve got an IP address. But within each of these worker nodes, there are dozens if not hundreds of pods or containers running workloads for us, and each of these pods has a unique IP address assigned to it by the CNI, or container network interface. So when I say routable pods, what that means is that the network is aware of every pod and which node it’s on.
In AWS, this is solved using something like the AWS CNI or Cilium ENI mode, where the CNI will actually talk to the AWS API and say, hey, can I have an IP address, or a /28 or a /80 prefix? And the hypervisor knows that that prefix or IP address lives on that NIC and knows how to route to it. But when we’re going back to bare metal, all of those primitives don’t exist. So while connecting to hyperscalers is a fairly well-known and documented process, what I’m going to walk through now is how a number of different neocloud providers integrate with your network, both from a node and a Kubernetes perspective.
All right. Provider A: bring a router. This provider gave us a layer 2 domain and the ability to run virtual machines with multiple NICs, but no routing. So we went BYO. We brought a router. It’s a virtual machine, and it provides a first-hop redundancy gateway. You can see VRRP down there. It’s been a long time since I’ve configured VRRP. And we do dynamic BGP down to our nodes.
Just a quick note on the dynamic BGP. Folks that have run a Kubernetes environment will be familiar with this, but typically a lot of the CNIs will assign a prefix to a node. And how does your network know what node has what prefix? That’s where BGP comes in. Why dynamic BGP? Because these nodes are coming and going constantly. Folks that have configured BGP, you typically punch in a static IP address for your neighbor: here’s the set of capabilities and configuration that we’re going to negotiate. That doesn’t work so well when you’re getting 100 alerts because a couple of nodes rebooted. So we use dynamic BGP.
Now, for this particular provider, fiber interconnects are hard to get in the regions that we use. So it phones home over the internet, and that works well, but that virtual machine is now in the critical path. We’re no longer outsourcing that operational complexity to the provider, so we have to consider that very carefully. And on top of that, it’s got throughput limits, so we’re at the mercy of the internet underlay.
Lessons learned. Just like during our first steps building out that proper WAN with a NaaS provider, we learned that hyperscalers have some network rate limits. Some of you would be familiar with this. Typically, the more CPU you throw at a virtual machine in a cloud, the more network throughput you can get. Maybe there are network-optimized instances. This is very well documented, known, and productized. But in some of these neoclouds, it turns out that they also have rather aggressive rate limits, and we had some instances where VMs weren’t able to achieve more than 1 or 2 gigabit. We needed a lot more than that. Sometimes there are workarounds to these constraints, but I guess the lesson learned is that performance testing is absolutely critical for uncovering these issues.
Bring everything. So we’ve just brought a router, and now we’re bringing everything. In this case, Provider B was happy to interface with fiber, but had no virtual machines. A lot of neoclouds don’t have those virtual machine capabilities, like I mentioned. And in this case, the internet was also heavily capped, so I can’t run a virtual router, and I can’t use the internet anyway to phone home using an SD-WAN-style capability.
There’s no routing either, so literally everything is ours. We have to run VRRP like the previous provider, but now we’re also providing things like DHCP, and we’re still doing that dynamic BGP. Now we’re doing literally everything. You can see down the bottom, all platform connectivity concerns are now managed by us. So we’re essentially running a small data center network on somebody else’s layer 2, and after years and years of cloud abstractions, we’re back to the absolute fundamentals.
It might seem trivial to folks that do on-prem: just chuck a pair of routers in the rack next door, sweet as. But we operate in an environment which doesn’t have any on-prem infrastructure. This would be completely foreign to us. And it also needed to be done in days, not months. New data center provider, racks, cabling, cross connects. If you can do all that in days, I would be impressed. Something else in the diagram, down the bottom there, which I just mentioned: the vendor manages the cabling and layer 2. So you could almost say at this point that we’re essentially just outsourcing that rack-and-stack and cabling capability.
All right. Bring a Kubernetes controller. So we’ve had providers A and B, bring a router and bring everything. This one’s bring a Kubernetes controller. This one actually looks the easiest on paper. This is a proper cloud. It’s got real VPCs. They own the route tables.
The problem that this created is in the Kubernetes layer now, because there was no integration with our CNI. I briefly touched on how, in AWS, you make an API call, and it knows that that IP address or prefix is on a particular NIC. We didn’t have any of that automation built in. Where the hyperscalers solve this for you and tie the CNI into their native constructs, this provider only solves it with their own managed Kubernetes. But we also couldn’t drop in our own router, because they own the route table in this case. There is no layer 2, like Holly mentioned in her talk.
So we had two choices. We could either adopt their Kubernetes and diverge our platform, and we had a lot of tooling built around our Kubernetes platform, a whole bunch of release and deployment processes and all that sort of stuff. Or, and this is the option that we picked, we actually wrote a Kubernetes controller. What that controller does: the cluster is aware of which node has which prefix, and this controller actually reaches out, touches the API, and updates the route table. So now that route table is aware of which prefix, in our case a /26 in this cloud, lives on which node.
All right. Just bring yourself. From a networking perspective, by far the easiest. This one is pretty much our benchmark. We get a pair of high-speed fiber interconnects and redundant BGP sessions to their routers, and they handle everything. So if there’s node and pod route aggregation, and I mentioned /26 before, they all get rolled up into whatever our prefix is, say a /18, or a /64 for v6.
But unlike a hyperscaler, with a lot of strict guardrails and quotas and that sort of thing, on this side there were actually humans assisting in the process, so we could do pretty much anything from a network integration perspective. And when a provider gets this right, the network team, so my team, barely notices them, so kudos to them. It’s really just a pair of high-speed links and redundant BGP connections, and all of the aggregation is handled. Platform concerns, DHCP, VRRP, gone, a distant memory.
So putting all of these together, we actually realized there’s an interesting U-curve of complexity, with ease of integration on the x-axis and how much of the network the provider owns on the y-axis, or have I got those axes back to front? A more capable cloud can actually be harder to integrate than a simpler one. On the left-hand side there, you can see bring a router. Pretty easy, layer 2 only. Bring everything, somewhat easy, also layer 2. But then down the bottom here is this real dip, where we had to bring a Kubernetes controller and cut actual software. We’re not just talking network integration here. We’re talking a full software package in that controller. And then straight up the other end, just bring yourself. They own everything, and the hyperscalers are all up that end as well.
All right. We’ve done a few neoclouds over time, and we’ve run into some obscure issues. Distributed computing fallacies apply to unprepared workloads. What does that mean? Well, the computing fallacies: latency is zero, bandwidth is infinite, the network is reliable. We grew up in one cloud and one region, and there’s a lot of data in that region. Data has gravity. It’s hard to move. It’s expensive to move, and it costs a lot to store when you’ve got lots of it.
But now we’re in a world with neoclouds, where you’re dropping workloads wherever you can get GPUs or compute. So what workloads, and particularly application teams, have to be aware of is that those fallacies do not apply. Latency is definitely not zero, and bandwidth is definitely not infinite, and we just need to tune for that as appropriate.
This next one, default ARP setting, is basically a warning to say that clouds, neoclouds, and hyperscalers may do interesting things with the default builds and images that you deploy in them. In this case, a default ARP setting suppressed replies for the pods. This was from a hyperscaler, basically disabling internal ARP on that virtual machine. And there’s a bunch of other stories similar to that I could share, about how we actually hit the ARP table limitations in one cloud, which I think was 2,000 by default in Ubuntu.
Full IPv6 support is still rare in the wild. Some of you who are more familiar with Kubernetes are probably familiar with the fact that it eats IP addresses for breakfast. How are we doing all of these routable pods with IPv4? Well, the short answer is IPv6. And still to this day, in 2026, it’s difficult to get full IPv6 support. It’s rare in the wild.
And the last one down here ties into those distributed computing fallacies a little bit. Storing 1 gig for a month often costs the same as downloading it once, and some of the other talks are going to go into a bit more detail on that. But what if you have to download it twice? Does it then make more sense to just replicate it and then download it for free infinitely?
Speaking of free, cost engineering for fun and profit. All right. Cost saving tip number one. By pivoting to NaaS providers with virtual routers and internet access, we’d actually already built a way to achieve ubiquitous inter-cloud connectivity. So why not just pop a firewall on those routers?
Very obviously, this removes managed NAT gateway and managed cloud-native firewall processing fees and all that sort of stuff. And you can see that we’ve got a number of different clouds plugged in here. This is now a standard egress deployment for every cloud. We’re not using a proprietary cloud number one solution and cloud number two solution. And in the case of the neoclouds, which have no native firewalling, this ensures our egress controls are in place for the entire network, not just the hyperscalers.
So throwing out a hypothetical: 1 petabyte of transfer each way, a download and an upload. On the download, ingress to the cloud is typically free, so you’re paying processing fees. Let’s just say it’s 6.5 cents a gig. So for 1 petabyte, that’s $65,000. On the upload, you’ve got data transfer out as well, plus your firewall processing fees, so about $115,000, or $180,000 in total.
The flip here is, what if you had some sort of fixed-rate transfer through a NaaS provider? If you have consumption-based billing versus fixed-rate billing, you are always going to have a break-even point. And so you’ll have to do your own math on what your download versus upload patterns are, but essentially, beyond that break-even point, it’s definitely going to be more worthwhile just to outsource it. So on the upload, perhaps now you’re only paying Direct Connect fees out, and the download is still free on Direct Connect ingress into the cloud.
But everything in tech has trade-offs. I think it was Russ White who said if you can’t find the trade-offs, you’re not looking hard enough. So moving your egress to a NaaS provider, just like regular on-prem networking, means you now own the capacity management. Cloud is all about elasticity. If you’ve got a really elastic workload that goes from zero to 100 gigabit and does that for maybe an hour a day, well, bad news, you’re probably going to have to size for peak capacity, which means you’ve got unused capacity for those 23 hours. Alternatively, you’re going to have to manage expectations around performance. Your job no longer takes an hour, it now takes four hours, or something along those lines.
There’s also a reliability piece to this. Cloud-native firewalls have been engineered to ensure resiliency to failure scenarios, and now you own that. So it’s no longer a case of, we’ll pop an endpoint in AZ one, two, and three, and job done, everything just works. You’re now on the hook for that firewall going bad.
Just a slight side quest on this one, on the reliability side. There are ways to do this from a NaaS perspective. One of the things that we played with was actually injecting a pair of, and we’re talking v4 here, a pair of /1 routes into the VPC. What that means is we’ve got these two routes, which cover the entire internet, dynamically coming in through BGP on the Direct Connect product, and then we kept the static 0.0.0.0/0 route. So that meant that in the event, which should not happen, that both of our firewalls and routers went down in that particular POP for that metro, both of those dynamic /1s would be withdrawn, and the static 0.0.0.0/0 would take over and start hitting the cloud-native stuff, just as a bit of a fail-open circuit.
Cost saving tip number two. This one is pragmatism over perfect design, otherwise titled: cut your inter-AZ costs by one third with this one simple trick. For VPCs that talk to each other, we use VPC peering instead of Cloud WAN. We’ve got universal connectivity across every region, in this case via the Cloud WAN, but you can see there we’ve got three hypothetical regions, each with two compute VPCs and a resource VPC. We actually scale out our compute horizontally in some regions, just based on breaking apart that blast radius. They all talk back to a resource subnet, and there’s a lot of traffic going between, in this case, three VPCs in that region.
So we have universal connectivity, everything can talk, but for those cheaper regions, I beg your pardon, for those high-affinity links, you don’t pay for intra-AZ connectivity anymore. VPC peering is free within an availability zone and 1 cent in either direction, slightly confusing terminology, across AZs. Cloud WAN or Transit Gateway, or pick your other product, NCC from Google, are typically about 2 cents per availability zone.
So in a typical region with three availability zones, setting aside application-layer optimizations, which honestly are probably the better option, or topology-aware routing and those sorts of things, if you’re doing 1 petabyte from one AZ to itself and two other AZs, we’re now comparing $60,000 with Transit Gateway or Cloud WAN versus $40,000 using that peering link. So straight away, that’s a one-third saving, because that intra-AZ stuff is free.
And the pragmatism comes in here because, as networkers often operating at high scale, we try to simplify everything, and it is a beautiful design to have a hub and spoke with every VPC nice and standard, nice and simple. But in this case, the cost-effectiveness overrode that simplicity.
All right, cost saving tip number three: private VIFs, not transit VIFs. Similar to the last one, where I was talking about that processing fee, with our hybrid networking we also bypass the Cloud WAN or transit gateway or cloud router if possible. On the AWS side, we use private VIFs into Direct Connect gateways rather than transit VIFs. That means the inter-cloud routing doesn’t pay that 2 cents per gigabit processing fee, and we run a DX gateway per POP. That gives us fine-grained routing control. And you can also see there that there’s one per segment, but that’s nice and simple these days, as I’ve talked about before.
But trade-offs: this is now creating an operational cost. How many DX gateways are we going to have? What issues are we going to run into? And for us, being a software shop, everything is infrastructure as code. From a scale perspective, this is actually trivial. I don’t need to worry so much. You can have up to, I believe it’s 50 private VIFs, and each of those VIFs can have up to 20 VPCs. So that’s 1,000 VPCs per region, as we do per-region DX gateways. Plenty for most. And saving 2 cents a gig on every petabyte of data that we transfer is basically a top-of-rack switch for your data center.
So, lessons learned. There have been some recent changes to how these quotas are managed, but typically VIFs had a quota limit of 100 routes per BGP session. If you hit 101, your BGP goes down, alerts go off, and you’ve got to figure out what the heck just happened.
We actually got that quota lifted, but then we hit the next issue. We were no longer dropping BGP at 101 routes, but it turns out there was a secondary quota: because of this private VIF architecture, the maximum number of propagated routes going into a VPC was still 100. And so route 101 didn’t drop BGP, but it was just put in the bin by the VPC route table. The VPCs all ignored it. And in one region, that actually got stuck, and even when we withdrew routes, it needed a support ticket to get fixed.
So the solution for us in this case was aggressive region-based summarization into the hyperscalers. They’ve still got that cap of 100 in the case of Amazon, and I believe it’s 300 in the case of Google. But then it was juggling: do we advertise a 10.0.0.0/8 from the DX and then have more specific region routes in the VPC? In the end, what we did was have per-region summarization and just leave that simple static route in our Terraform code that points back to the Cloud WAN for inter-AZ traffic.
All right. Everything we learned along the way. I’ve been hitting these points quite a few times. The wrong complexity doesn’t scale. Sometimes infrastructure as code is a good trade-off, and that does help you scale a little bit more.
With great control comes great operational overhead. With a lot of the solutions that I’ve mentioned, you need to take on an extra load. Some of those you can make go away with code. Some of those you’ll need to pick up in your observability. Some of them might just simply need more engineers, and there’s always a trade-off. If you can shave $1 million off of your cloud hyperscaler bill, how many engineers does that buy you?
And the last one, this one’s really tricky. You could almost do a PhD on this. Know your cost per gigabit or gigabyte for every path.
All right, that’s a wrap from me. Thank you very much, everyone, for listening. And feel free to hit me up on LinkedIn for any fun tips on how many copper cores and steel cores were in field cable back when I was in the army, or to talk about cloud networking. Thank you.

Need help mapping your cloud infrastructure path?
With a Megaport Solutions Architect
Find out how to connect your business in 60 seconds.
We’ve helped hundreds of customers, just like you, to simplify their connectivity.




