
Egress Decides Your Architecture, and It Arrives Three Months Too Late to Argue With
Data transfer out is the only cloud cost that is set by design rather than by configuration. By the time it shows up on a bill, the decision that caused it is already load-bearing.
Compute is a dial. Storage is a dial. If either is too expensive you resize an instance, change a tier, delete some snapshots, and the next bill responds. Egress is not a dial. Egress is a consequence of where you put things relative to each other, and by the time it is large enough to notice, the thing generating it has been in production for a quarter and has dependents.
That asymmetry is the whole problem. Every other cloud cost gives you a lever after the fact. Egress gives you a rewrite.
The bill tells you the total and hides the cause
An invoice line reading "data transfer out" is a single aggregate across everything you run. It does not say which service, which caller, or which query pattern. Finding the cause means reconstructing traffic flows from network logs after the fact, which most organisations have not enabled at the granularity required, because that logging itself costs money.
So the sequence goes: month one, the workload ships and the bill is noise inside a larger total. Month two, someone notices transfer costs have grown. Month three, an investigation starts. Month four, the cause is identified as a synchronisation job or a reporting tool that pulls a full dataset across the boundary on a schedule. By then the reporting tool has forty saved dashboards and an executive audience.
The mechanics of how this accumulates in a two-sided estate are worth understanding before you design anything, because the way egress charges actually accrue in hybrid architectures is not intuitive: the expensive traffic is rarely the traffic anyone thinks of as a data transfer. Nobody budgets for a chatty API. They budget for backups.
What actually generates it
Four patterns account for most of it, and only one of them looks like data movement.
| Pattern | Why it grows | Why it is hard to fix later |
|---|---|---|
| Half-migrated application talking to an on-premises database | Query count was free when the hop was local, so nobody counted it | Fixing it means changing the data access layer, not the network |
| Reporting or BI tool pulling full extracts | Extract-based tools default to full refresh, and refresh frequency creeps up | The dashboards became the reporting process |
| Backup or replication running outbound | Sized against the full dataset, runs nightly forever | Retention and RPO commitments are already signed |
| Cross-region or cross-zone chatter inside the cloud | Invisible in architecture diagrams that show logical services, not placement | Service placement is baked into deployment templates |
The fourth is the one that surprises people who believe they have no hybrid boundary at all. Traffic between availability zones, or between a service and a managed database in another region, is billable in most providers and appears under the same heading. A microservice mesh spread across zones for resilience generates continuous internal transfer as a design property, not as a fault.
The first is the most consequential. When an application moves and its database does not, every query becomes a chargeable round trip. Application code written against a local database makes far more queries than its authors ever tallied, because the cost of a query was measured in microseconds and nothing else. Change the topology and that same code becomes a per-gigabyte meter. This is why the networking design work for connecting on-premises systems to cloud has to happen before the first workload moves rather than after: interconnect options, private paths, and where the boundary sits all change the unit economics of the same application.
Egress is a placement problem wearing a billing costume
The reason egress cannot be optimised away is that it is not really a cost of transfer. It is a cost of having put the compute and the data in different places. Compression helps at the margin. Caching helps where the same bytes are read repeatedly. Neither addresses the case where a process genuinely needs to read a large, changing dataset that lives elsewhere.
Which means the only durable fix is to move the compute to the data, and the only way to know when that is possible is to have thought about mass and movement before the split existed. Data gravity and where workloads actually belong is the frame that makes egress predictable rather than surprising: a dataset above a certain size and rate of change stops being something you move and becomes something you build around. Everything that reads it should be beside it. Everything that only summarises it can be elsewhere, provided the summarising happens on the data's side of the line.
That is also the practical mitigation for reporting. Aggregate before the boundary, ship the aggregate. It sounds obvious and it is routinely not done, because the BI tool was procured by a different team who quite reasonably pointed it at the source.
Five things to do before the workload ships
- Estimate the transfer volume as part of the design, in gigabytes per day, per data path. If nobody can produce a number, that is the finding.
- Draw the physical topology, not the logical one. Which region, which zone, which side of the boundary. Logical service diagrams hide every cross-zone charge in the estate.
- Count the queries, not just the payloads. Run the application against a database with artificial latency and see what happens to page load. The result predicts both the bill and the user complaints.
- Enable flow logging at the boundary from day one, and accept its cost. Attribution after the fact without it is guesswork.
- Set a threshold that triggers a design review, not just a cost alert. A cost alert tells you to ask for more budget. A design review asks whether the placement was right.
What to do next
If you already have the bill and not the cause, start with the flow logs you do have and rank paths by volume rather than by suspicion. The top two paths almost always account for the majority, and one of them is usually a scheduled job nobody owns.
If you are still at design stage, the useful discipline is to treat every proposed boundary crossing as a commitment with a recurring cost attached, in the same way you would treat a licence. Boundaries that survive that test are the ones worth building interfaces for. The rest are accidents you have not paid for yet.
Where the answer is that the boundary has to exist, it deserves proper design rather than a VPN and hope. That is the scope of our hybrid cloud integration work: deciding where the line sits, what crosses it, and what the crossing costs before it becomes a number on an invoice.
Fastnexa Cloud Practice
Cloud Services Team at Fastnexa. We write from real client work, and we are happy to talk through yours.
Ready to ship this?
Bring this problem to a free 30-minute call with the team that wrote the post.
Book a demoMore from the blog
View all
Your Cloud Account Structure Is a Security Decision Nobody Labelled as One
Account layout usually gets decided by billing convenience in the first month of a cloud programme. It is also the strongest blast radius boundary the platform offers, and changing it later is a migration.

Identity Is Your Cloud Perimeter, and Least Privilege Dies the First Time It Blocks a Deploy
Least privilege is not lost to a policy failure. It is lost at three in the afternoon when a role is too narrow, the release is waiting, and widening the policy is the fastest way through.

The Shared Responsibility Model Is Read as a Promise and Written as a Boundary
Providers publish the shared responsibility model to establish where their liability ends. Customers read it as a statement about how much security they are getting, which is the opposite of its purpose.
Related services
Want help putting this into practice? Here is how we deliver it.