Skip to main content

Docker Cancels Hub Pull-Rate Charges Outright: What Walking Back a Pricing Threat (Not Just Postponing It) Signals About Registry Cost Risk on Owned Hardware

9 min readDora NodaDora Noda
Share
On this page

In November 2024, Docker told the world it was putting a meter on Docker Hub: tiered monthly pull ceilings — 25,000 for Pro, 100,000 for Team, 1,000,000 for Business — with an overage charge to follow once you crossed them, plus storage-based billing on top. By April 2025, all of it was gone. Not delayed again. Cancelled. Paid-tier pulls became unlimited, storage billing was shelved indefinitely, and Docker committed to at least six months' notice before trying anything like this again.

That's a different kind of reversal than the one Docker had already pulled once, in February 2025, when it pushed the March 1 start date to April 1 and called it a delay. A delay says "not yet." A cancellation says "not this plan." If you're running a self-hosted PaaS on owned hardware — pulling images from Docker Hub into a Cluster API fleet you provisioned yourself specifically to get off metered cloud billing — that distinction is worth taking seriously, because it tells you something concrete about how much registry cost risk is actually still on the table today, versus how much was reversed on paper.

The timeline: threat, delay, and then an actual walk-back

Three dates carry the whole story, and the gap between the second and third is the part worth sitting with:

DateWhat happenedDelay or cancellation?
November 2024Docker announces consumption pricing: monthly pull ceilings by tier (25K / 100K / 1M for Pro / Team / Business), storage billing to follow, enforcement set for March 1, 2025— (the threat)
February 2025Start date pushed from March 1 to April 1; personal-tier limits loosened slightly; storage billing "delayed indefinitely"Delay
April 2025Pull consumption charges cancelled outright for paid tiers — unlimited pulls with fair-use limits, no overage fee ever shipped; storage billing still shelved; Docker commits to 6 months' notice before any future attemptCancellation

Notice what never happened between November 2024 and April 2025: Docker never published an actual overage rate. The tiered pull ceilings were public and specific — 25K, 100K, 1M pulls a month — but the dollar figure for what happens when you cross one was never announced before the whole plan was scrapped. That's the tell that this was a full walk-back and not a repricing: Docker didn't get to "here's what it costs," it got to "here's roughly what we were going to limit," felt the pushback, and cancelled before finishing the sentence.

What actually changed — and what quietly never did

Here's the part that gets lost in "Docker cancelled the fees" headlines: the consumption charge is what got cancelled. The rate limit is a separate mechanism, and it was never part of the walk-back. Docker's current published limits, per its pricing FAQ, are:

  • Unauthenticated pulls: 10 pulls/hour, per IP address
  • Docker Personal (authenticated, free): 100 pulls/hour, per user
  • Paid plans (Pro/Team/Business): no hourly pull limit

Those numbers are throttling, not billing — you don't get charged for the 11th unauthenticated pull in an hour, you get a 429 Too Many Requests. And unlike the consumption-pricing plan, none of this was walked back. It's been live, in some form, since 2020, and it's still live today.

For a solo developer that's academic. For a Cluster API fleet on owned hardware, it's a real operational hazard, because of how those fleets are typically networked: nodes usually sit behind a small number of NAT'd egress IPs, or in some setups a single shared one. That means the 10-pulls-per-hour unauthenticated ceiling isn't per-node — it's per-IP, shared across every node and every tenant pulling through it.

Run the numbers on two fleet sizes to see where the threshold actually sits:

  • A small fleet — a handful of tenant apps, one or two deploys a day — barely touches the limit in normal operation. A single git push triggering a rebuild and one pull per affected node is 2-3 pulls, nowhere near 10/hour, and even unauthenticated traffic clears fine most days.
  • A larger fleet under a Cluster API node-replace or scale-out event — the exact moment a machine gets recreated and Kubernetes reschedules 20-30 pods onto it, each pulling its own image, all from the fleet's shared egress IP, inside the same few minutes — blows straight through 10/hour unauthenticated on its own, from one legitimate operational event, with zero abuse involved. Do that twice in the same hour (a flaky node plus a routine autoscale) and even the 100/hour authenticated Personal-tier ceiling, if that's what the fleet is configured with, starts looking uncomfortably close.

That's the actual risk that survived the reversal. It was never really a pricing story for an owned-hardware operator — paying per pull was never going to bankrupt anyone at Hub's proposed rates. It's an availability story: a rate limit that throttles a bulk reschedule at the exact moment a fleet needs every pod back up, and it applies today with the same force it did before Docker cancelled anything.

The fix isn't about Docker's pricing at all

Once you see the rate limit as the live risk and the pricing plan as the dead one, the fix stops being "wait and see what Docker does next" and becomes an infrastructure decision the operator makes once: put a pull-through cache in front of Docker Hub, on the same hardware the fleet already runs on.

A pull-through cache — Harbor, the CNCF Distribution registry's built-in proxy mode, or the lighter-weight Zot — sits between the fleet and Docker Hub. The first time any node requests nginx:1.27, the cache pulls it from Hub once and stores it. Every subsequent pull, from any node, for that same image, is served from the cache and never touches Hub's rate limit at all. The node-replace scenario above — 30 pods rescheduling and repulling nginx, postgres, and a tenant's own app image simultaneously — turns into one real Hub pull per unique image, ever, and thirty cache hits that don't count against anything.

The cost comparison here isn't Docker Hub egress versus Hetzner egress — Hub doesn't charge for bandwidth, so there's no dollar figure to substitute there. The real comparison is what it costs to run the insurance on owned hardware versus what the same insurance would cost bolted onto metered cloud infrastructure.

A mirror serving images from cache to the fleet's own nodes is internal traffic on hardware you already own. On a Hetzner-class node, that traffic sits inside the 20TB of included monthly bandwidth that ships with the box, with overage priced around $1/TB if you ever blow through it. On a cloud provider billing egress at AWS's roughly $90/TB list rate, that same internal mirror traffic is a real, growing line item as the fleet scales. Owned hardware doesn't remove the rate-limit risk on its own — but it makes the fix for that risk close to free, which a metered cloud deployment doesn't get for free.

"The vendor backed down" isn't "the vendor won't try again"

It's worth being precise about what Docker actually promised, because "cancelled outright" and "permanently ruled out" aren't the same sentence. The commitment on record is six months' notice before any future consumption-pricing attempt — a process guarantee, not a promise never to revisit it.

Docker Hub is still, by its own description, the world's largest container registry, and it still needs to fund the bandwidth and storage that implies. The November 2024 plan is evidence the idea has already been seriously considered once inside the company. Six months' notice means a future attempt won't ambush anyone the way the original March 1 deadline nearly did — it doesn't mean there won't be one.

That's the real argument for building the mirror now rather than treating this as a closed story. A pull-through cache doesn't just fix today's rate-limit exposure during a bulk reschedule — it's the same piece of infrastructure that would insulate a fleet from a future consumption-pricing plan, if Docker ever gets far enough into one to publish an actual overage rate. Building it in response to a specific incident is reactive; building it because the underlying dependency on a single external registry was always the risk, independent of which enforcement mechanism Docker happens to be using this year, is the version that doesn't need to be revisited every time Docker's pricing team writes a new blog post.

The dependency was always the point

Strip away the billing-versus-throttling distinction and what's left is an old infrastructure lesson wearing new dates: a self-hosted PaaS that owns its compute but still routes every image pull through one external registry hasn't actually removed its dependency on someone else's infrastructure decisions — it's just relocated where that dependency shows up. Docker Hub's 2024-2025 pricing saga made that visible because it was loud and public, but the rate limits that survived it were doing the same job quietly the whole time, and they still are.

Owning the hardware was never going to be sufficient on its own; it has to be paired with owning the parts of the supply chain that can throttle or meter you regardless of who's running your compute. A pull-through cache is a small, boring piece of infrastructure — a few hours of setup, a modest amount of disk, no ongoing bill worth mentioning on owned hardware — for something that removes a real failure mode a Cluster API fleet will eventually hit on its own schedule, not Docker's.

Bex.co runs Cluster API fleets on owned hardware and treats the registry layer the same way it treats compute and networking — as infrastructure the operator controls, not a dependency to hope stays free. Check out the project on GitHub if you're evaluating what it takes to own that layer yourself.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex