usage-meteringcapstone

Usage Metering & Billing Engine

A usage-billing backend built around retry-safe event recording, explicit quota decisions, and integer-based cost rollups.

Node.jsExpress 5Prisma 7PostgreSQLStripeZod
0
stored event for same-key retries
0
plans: Free and Pro
0
metered usage types
0
Stripe webhook event types handled

A backend service that records API-call and AI-token usage, enforces Free and Pro plan limits, calculates usage costs, and syncs subscriptions through Stripe test-mode billing.

01

The problem

Charging every customer the same monthly amount can be a poor fit when usage varies widely: heavy users may cost an organization more to serve than their subscription covers, while light users can pay for capacity they barely use. A usage-based approach can make costs more proportional to consumption, but only if usage is recorded reliably, quota boundaries are enforced clearly, and small event costs are aggregated without rounding them away. Retries must not create duplicate billable events, and a request at the limit must be treated differently from one that exceeds it.
02

What I built

I built an Express API with Zod validation at the request boundary and a layered route, middleware, service, repository, and PostgreSQL design. The metering service checks for an existing event by tenant and idempotency key; a database uniqueness constraint and conflict recovery make concurrent retries of the same key resolve to the stored event. Quota enforcement checks subscription standing before the plan limit, returning 402 for a subscription that is not in good standing and 429 when the request would exceed its monthly allowance. Costs are calculated in integer micro-cents, with period totals summed before conversion to cents; the usage endpoint returns the resulting cost totals. Customers can pay for the fixed-price Pro subscription through Stripe-hosted Checkout ($29/month in the documented test setup). Stripe processes the subscription payment; signed, deduplicated webhooks report checkout and subscription events so the service can synchronize subscription status and the tenant's plan. The measured usage cost is reported by the API but is not separately charged through Stripe. A scheduled job checks usage-alert thresholds and records its runs, retrying failures up to three attempts with backoff. The scope deliberately uses a trusted x-tenant-id header rather than real authentication and UTC calendar months rather than Stripe billing periods. Quota checks and event insertion are separate operations, so concurrent requests with different keys can still overshoot a quota.

// how POST /generate is validated, metered, and priced
client
tenant + idempotency key
Express routesHTTP endpoints
middlewaretenant resolution + Zod validation
meter + quota servicesidempotency · 402 / 429
cost serviceinteger micro-cent pricing
repositoriestenant-scoped database access
PostgreSQL
usage events · unique tenant/key
// how Stripe collects the Pro subscription payment and the app syncs it
customer
starts Pro checkout
billing routePOST /billing/checkout
Stripe Checkout$29/month subscription · test mode
customer paysStripe-hosted subscription checkout
signed Stripe webhookcheckout.session.completed
webhook routeverify signature + deduplicate event
webhook service
save subscription · set tenant plan to Pro
03

Results & impact

◆

Verified same-key retries return the original response and create one usage row, including when two requests race on a new key.

◆

Verified quota boundaries: a Free tenant can reach exactly 1,000 API calls for the month, while the next call is rejected with 429; a past-due subscription is rejected with 402 before quota evaluation.

◆

Kept token pricing in integer micro-cents and verified period-level rounding: three 345,000-micro-cent events roll up to one cent instead of rounding individually to zero.

◆

Implemented Stripe Checkout and handlers for checkout completion, subscription updates, and subscription deletion, with signature verification and event deduplication.

◆

Added a scheduled usage-alert job that checks 80% and 100% thresholds, retries failures up to three attempts, and records successful or failed runs.

$ ./say-hello.sh

Let's talk about your backend.

Open to backend and platform engineering roles, and to interesting infrastructure problems. Fastest reply is by email.

© 2026 Elyas BromandBuilt with ♥ by Elyas Bromand↑ back to top