Back to Case Studies

How We Added Spend Guardrails to a Location-Aware Delivery API

Simon Hughes·23 April 2026· 5 min read
campaign delivery APIcredit controlsgeo pricing
How We Added Spend Guardrails to a Location-Aware Delivery API cover image

Balancing ad serving speed with campaign budget safety in a creator marketing platform.

Context

This project centered on a creator marketing platform that serves adverts to third-party screens and apps in real time. The delivery side was built as an Express API with token-gated endpoints, while campaign and billing data lived in Prisma models behind a GraphQL back office. On paper, the workflow was straightforward: fetch eligible adverts, track impressions and clicks, and deduct credits. In practice, this had to stay safe under lots of edge cases like empty balances, location-based price changes, and different campaign states.

The platform already had campaign concepts like draft, approved, paused, completed, and out-of-credits. It also had pricing configs and zone tiers for location-aware rate calculation. The missing piece was making runtime spend behaviour fully predictable, so campaign owners could trust that delivery would never silently overspend.

Challenge

The hard part was not just calculating a rate per impression or click. It was making sure rate calculation, balance checks, campaign limits, and audit logging all behaved as one system.

If any one part drifted, operations got messy quickly. A campaign could keep serving after hitting a hard cap. A credit balance could drop without a clear transaction trail. House ads could accidentally consume paid credits. Daily and weekly limits could be bypassed if checks and writes were split badly. And because delivery calls happen fast and often, this needed to be safe without turning into a slow, fragile path.

There was also a product reality to handle: campaigns should pause automatically when credits run out, then resume when credits are topped up. That sounds simple, but it crosses delivery, billing, and status logic.

Approach

We implemented the spend workflow around a dedicated CreditService and used it directly from delivery tracking endpoints. Impression and click routes in the delivery API pass campaign context into processSpend, which then handles one consistent sequence: check house ad behaviour, compute rate, enforce limits, update balances, and write telemetry.

Rate calculation supports a default base rate and a zone-aware path. If coordinates are present, lat/lng are snapped to a grid and matched against the active pricing configuration and tier multiplier. That allowed localized pricing without exposing internal pricing mechanics to delivery clients.

For spend integrity, we used a transaction to bundle org balance decrement, credit transaction creation, and campaign total-spent increment. We then recorded raw event rows and upserted hourly and daily aggregates for analytics and dashboard rollups. This gives a clean chain from runtime event to finance trail to reporting.

Status safety was built into the same flow. If credits are insufficient, approved paid campaigns move to out_of_credits. If a hard limit is hit, the campaign is marked completed. If a campaign is a house ad, events still get tracked but amount stays zero and no credit deduction happens.

We also kept the behaviour test-driven. Unit tests cover house ad handling, insufficient balance pausing, hard-limit completion, daily-limit blocking, zone multiplier pricing, and resume behaviour when balance is replenished.

Outcome

The delivery path became easier to reason about for both engineering and operations teams. Runtime serving still stays fast, but there are now explicit control points that prevent budget surprises.

Support conversations also got cleaner. When a campaign stops serving, the reason can be traced through status changes and ledger entries instead of guesswork. When spend is questioned, there is event-level data plus hourly and daily rollups to inspect. When credits are topped up, campaigns can resume automatically instead of waiting for manual intervention.

No vanity metrics were needed to see the value. The practical win was fewer ambiguous states, tighter financial control, and a campaign workflow that behaves consistently under pressure.

Key takeaway

In ad delivery systems, budget logic has to be treated as product-critical runtime behaviour, not a back-office afterthought. Putting spend control, ledger writes, and status transitions behind one service boundary created a safer and more maintainable delivery engine.