smallbox

← All articles

What one capability unlocks

How do you keep a pay-per-call maps API from scaling your bill with your traffic?

Maps and geocoding: the cache and the cost ceiling are the product

Adding a map is one of the more satisfying afternoons in this work. You paste a key, drop a pin, type an address, and a hosted geocoder hands back a latitude and longitude that lands exactly where it should. It feels finished. The thing the afternoon hides is that this particular capability bills you every single time it answers, and the bill is shaped by traffic you haven't seen yet rather than by anything you decided.

That's the line worth drawing early. A maps-and-geocoding API — Google, Mapbox, one of their peers — meters per call. Each pin drawn, each address resolved, each route computed is a charge. And the inputs repeat far more than first instinct suggests: the same store address, the same depot, the same handful of cities get looked up again and again. So the ownership question for this capability isn't "can I call it" — you can, today. It's what do I own so the bill doesn't scale with traffic I never planned for.

What the capability gives you, and what it charges for

The provider does a genuinely hard job. It holds a global map, keeps the tiles current, runs a routing engine that knows about one-way streets and traffic, and turns the messy string a human typed into a precise coordinate. None of that is yours to build, and trying would be a different company. Rent it.

What you're renting, though, is a meter. The provider's pricing is per request, and every public price list has a free tier that ends and a per-thousand rate that begins. The capability is sound; the cost model is the part that needs an owner on your side. Left unmanaged, it has exactly one failure mode, and it's a cruel one: the product gets more popular, more pages load, more addresses resolve, and the bill climbs in lockstep with the success. Growth and cost arrive coupled, and nobody chose to couple them.

What stays yours, and what doesn't

The split is clean. Leave the map tiles, the routing engine, and the geocoding model with the provider — those are the hard external jobs you're paying for. Keep three things at home.

The first is the cache. An address resolved once should not be paid for twice. A geocoding result is stable — a street address maps to the same coordinate today and next month — which makes it almost the ideal thing to remember. Store the resolution keyed to the input, check your own store before you reach for the meter, and the endless repetition of the same addresses stops being a recurring charge and becomes a one-time one. This is the single largest lever you have over the bill, and it lives entirely on your side.

The second is the cost ceiling. A pay-per-call API has no natural brake of its own — it will happily answer the ten-thousandth call in a loop as readily as the first. So the brake has to be yours: a cap on calls per period, a guard around the kind of bulk operation that could fan out, a hard stop that degrades the feature instead of draining the account. A runaway loop against a metered API isn't a bug in the ordinary sense; it's an outage of the wallet, and the only place to prevent it is in your own code, before the call goes out.

The third is the usage log — a record of what you actually called, when, and on whose behalf. Without it, the monthly invoice is the first time you learn what your traffic cost, which is the worst possible time and the wrong place to learn it. With it, you can see a spike the day it starts, attribute calls to features, and tell whether the cache is doing its job or quietly missing.

What breaks when it's hacked in

The failure has a single shape: the call goes straight to the provider on every request, with nothing of your own between your traffic and their meter.

Skip the cache and every page load re-geocodes an address you already knew, so the same depot gets paid for on Monday and again on Tuesday, and the invoice grows with success rather than with anything new being learned. Skip the ceiling and one unbounded loop — a bulk import, a retry that doesn't back off, a map that re-resolves on every render — can turn a quiet month into a month you have to explain. And the version of this that hurts most is the silent one: you hit the provider's rate limit partway through a request, the call comes back empty or throttled, and the map simply renders without its pins while everything looks like it worked. No error reaches the user, no row reaches a log, and the feature is degraded in a way you only discover when someone reports that half the locations are missing.

That last one is why the usage log isn't optional bookkeeping — it's the difference between knowing you were throttled and guessing. The cache and the ceiling are nearly the whole discipline here; the map call itself is trivial. Get those two right and the provider becomes a part you plug in. Get them wrong and the provider becomes a variable cost that tracks your own popularity.

Where this rides, and where it already runs

Two of the three things you keep are not new capabilities you'd have to build — they're foundation work that already runs in production under CompanyGraph today. A scheduled background job is the natural home for warming and refreshing a geocoding cache off the request path, the same kind of batch runner that already does real work there on a cadence. And a log that records what was called and what came back — including the throttled call that returned nothing — is the same logging that every subsystem there already writes to, so a degraded result leaves a breadcrumb instead of vanishing. Those parts being already present is exactly why the new work is the cache policy and the ceiling, not the plumbing under them.

To be honest about the boundary: the studio has not built a maps product. CompanyGraph is evidence that the background jobs and the logging this capability leans on are real and running — not a claim that this geocoding idea has been shipped. Where a build would have to earn its keep is the cache-and-ceiling policy itself, against a real traffic pattern, and that part is genuinely unbuilt.

Where it shows up in a build idea

This capability is load-bearing the moment a product puts things on a map. A field-service SaaS — dispatch, routes, technicians on a map is the clearest case: it geocodes every job address and computes routes constantly, so the cache and the ceiling aren't optimizations there, they're the difference between a viable margin and a bill that climbs with every technician added. And the cost discipline itself is the same argument made about a different rented capability in a market-data alerting service, where a metered feed scales with how many users watch how many things — different provider, identical lesson: when you depend on something that charges per call, owning the limits is owning the business.

The verdict is plain, and it isn't "build your own map" — that would be the mistake. Rent the tiles, the routing, and the geocoder; that part is solved and worth paying for. Own the cache, the cost ceiling, and the usage log, because the one failure mode that defines this capability is a bill that grows with success — and that failure is prevented entirely on your side of the line, or not at all.


Maps wired this way are part of the modules a foundation already carries — the scheduled jobs and logging that keep a metered call from tracking your own traffic run in production under CompanyGraph today. The next sensible step is to read what that foundation already carries, so the only new work is the cache and the ceiling.

Articles describe the Foundation. The Foundation Map is the thing itself — accounts, admin, email, logging, and deployment, with one real workflow running through them.

← All articles