Meridian is a multi-tenant ocean-container tracking platform — 11 carriers normalized into one canonical schema, PostgreSQL Row-Level Security on every table, credit-ledger billing, and an adaptive polling scheduler that anchors every vendor API call to the vessel's predicted arrival instead of a cron clock.
A maritime logistics operator needed real-time visibility into ocean containers — where is the vessel, when does the box land, has anything slipped. The data exists: commercial tracking data providers expose it through clean APIs. The catch is the billing model. Those providers charge per API call, not per shipment. Every status check costs money whether or not anything changed.
The naive design — poll every active shipment on a flat 2×/day cron — burns roughly 60 polls over a 30-day voyage. And almost all of them are wasted. Container status is coarse: a box sits in IN_TRANSIT for the entire crossing and flips to ARRIVED exactly once. Fifty-nine of those sixty polls return the same answer as the poll before. Per-call vendor billing made flat polling uneconomical — the tracking data would have cost more than the tracking product could charge for it.
But you cannot simply poll less. Miss the arrival window and the customer's first notification of their own cargo landing comes from the port, not from you — which is the one failure mode a tracking product cannot survive. The problem, precisely stated: minimize vendor API calls without ever being late to an arrival.
The key observation is that the arrival isn't random. The provider's own payload carries a predicted ETA for the final destination, and it's the only event that matters. So instead of polling on a clock, Meridian polls on the ETA.
Meridian is not a script wrapped around a vendor API — it's a tenanted SaaS with database-enforced isolation, append-only billing, and a normalization layer that makes eleven heterogeneous carrier feeds look like one.
Tenant isolation is not enforced in application code — it's enforced by the database. All twelve tables carry Row-Level Security policies with FORCE applied, so even a query written without a tenant filter physically cannot read another tenant's rows. The API resolves the tenant from the authenticated session and sets it as the Postgres session context; from that point the database is the guard, not the ORM. The admin "God View" console — full cross-tenant visibility for operations — sits behind Keycloak with a separate role, and is the only path that legitimately crosses the boundary.
Billing follows the same discipline. Every trackable action debits a credit ledger that is append-only by design: balances are derived, never mutated, so a billing dispute is answered by replaying the ledger rather than trusting a counter. Upstream, an 11-carrier normalization layer maps each carrier's idiosyncratic feed — different field names, date formats, milestone vocabularies — into one canonical shipment schema, with a provider router that falls back across commercial tracking data providers behind a circuit breaker: five consecutive failures open the breaker and fast-fail for a cooldown window instead of hammering a degraded vendor. Outbound, every tenant webhook is HMAC-SHA256 signed so consumers can verify payload origin before acting on it.
The scheduler is a pure, dependency-free function: give it the shipment's status and the provider's final-destination ETA, it returns the next poll timestamp. Sparse mid-ocean, dense on approach, relentless when overdue — and never more than five days silent.
Each poll returns the shipment's status and the provider's eta_final_destination. A pure function maps that pair to a phase: cruise (ETA more than 3 days out) polls every 5 days as a cheap heartbeat that keeps the ETA fresh and catches big schedule slips; approach (within 3 days of ETA) polls daily to catch the arrival flip; overdue (ETA passed, still in transit — a delayed vessel) stays daily until resolution. Terminal states — arrived, delivered, unresolvable — stop polling entirely. A shipment with no usable ETA yet probes every 2 days until the carrier data catches up.
The subtle bug in any phase scheduler: if the ETA is 4 days out and the cruise cadence is 5 days, a naive implementation schedules the next poll after the vessel has already arrived — skipping the entire daily approach phase. Meridian clamps the cruise interval so the next poll lands exactly at the approach boundary (ETA − 3d), floored at one day so it is never sub-daily. The scheduler can be sparse, but it can never be late.
The scheduler trusts the provider's ETA — but only so far. A wildly wrong ETA (a vessel rerouted, a data glitch reporting arrival months out) could otherwise defer a shipment indefinitely. A hard backstop guarantees no active shipment is ever deferred more than 5 days, whatever the ETA claims. Worst case, a bad ETA costs a few extra heartbeat polls — it can never strand a customer's cargo in the dark.
The scheduler shipped behind an ADAPTIVE_POLLING flag with a shadow default: the system kept polling everyone exactly as before — zero behavior change — while logging what the adaptive scheduler would have done on every cycle: how many shipments were due, how many would have been deferred, and the projected call savings. Only after the shadow numbers validated against real arrivals over live poll cycles was the flag flipped to enforce. Rollback is unsetting an environment variable — no redeploy, no migration.
The entire cadence logic is a dependency-free pure module — status and ETA in, next poll timestamp out — which makes every phase transition unit-testable without a database or a mock vendor. The persisted next_poll_at column makes the scheduler's decisions inspectable in SQL, and phase labels flow into Prometheus counters so the cruise/approach/overdue distribution is visible on a Grafana dashboard, not inferred from logs.
The adaptive scheduler restored the product's unit economics without sacrificing a single arrival notification — and it shipped with the guardrails a production billing system demands.
Anchoring polls to the predicted arrival cut a 30-day voyage from ~60 vendor API calls to ~10 — roughly 6× fewer — because the mid-ocean cruise phase, where nothing ever changes, went from twice daily to once every five days. Per-call vendor billing had made flat polling uneconomical; the adaptive scheduler made the same product margin-positive with the same data provider and the same customer-facing freshness where it matters: the arrival window. The rollout was reversible at every step — shadow mode logged projected deferrals and savings against real arrivals before enforcement, and rollback remains a single environment variable.
The normalization layer collapses eleven heterogeneous carrier feeds — divergent field names, milestone vocabularies, date formats — into one canonical shipment shape. Every downstream consumer, from the React dashboard to tenant webhooks, codes against a single contract regardless of which carrier moved the box.
All twelve Postgres tables run Row-Level Security with FORCE applied, so tenant isolation holds even against queries that forget the tenant filter. The credit ledger is append-only — balances are replayed, never mutated — making every billed action auditable.
A Newman-driven Postman collection exercises the API end-to-end in CI on every push — auth flows, tenant boundaries, tracking registration, webhook contracts. The scheduler's phase logic carries its own unit suite, so a cadence regression fails the build before it ever burns a vendor call.
A Prometheus /metrics endpoint exposes poll counts, phase distribution, provider errors, and circuit-breaker state to Grafana. When a provider degrades or a cadence drifts, the dashboard shows it before a customer does.
I design systems where the economics are engineered, not hoped for — metered vendors, multi-tenant isolation, and rollouts that can be reversed with a flag.
Let's Work Together