Shipping Analytics Safely: Caching, Budgets, Deployment, and Handoff

Written by Rohan Nandan on September 12, 2026 · 5 min read

Article Image

Problem

A correct API is not automatically a production-ready platform. Analytics endpoints can become expensive, repeated requests can recompute the same results, stale outputs can mislead users, deployments can fail silently, and mobile clients can integrate against the wrong environment.

This project needed:

Without those properties, every new feature would increase operational risk rather than product value.

Approach

1. Cache derived analytics by user and type

Forecast and budget outputs are cached in the predictions table with explicit TTLs:

Prediction typeTTL
cashflow24 hours
runway12 hours
anomaly24 hours
budget7 days
budget_analysis7 days

Each cached row stores the requesting user, prediction type, serialized result, generation time, and expiry. Retrieval always returns the newest unexpired entry for that user and type.

This separation matters because forecasts change faster than long-run budget aggregates. A single cache TTL would either recompute stable budget outputs too often or serve volatile cash-flow outputs for too long.

Relevant code:

2. Invalidate on every relevant mutation

A cache is only trustworthy if writes and deletes invalidate it correctly. The API invalidates the affected user’s predictions when:

Account changes matter because balances affect forecasts. Recurring-rule changes matter because expected future transactions affect projections. Invalidation is scoped by user, so one user’s mutation never clears another user’s cached analytics.

That behavior is covered directly by integration tests. Cache tests check valid reuse, expiry and recomputation, mutation-driven invalidation, account and recurring-rule invalidation, and cross-user cache isolation.

3. Keep budget analytics explainable

Budget endpoints use transparent rule-based calculations over the prior three months:

Examples:

This makes budget recommendations auditable without requiring users to trust an opaque model. Category analysis separately reports totals, monthly averages, transaction counts, and shares of total spending.

Relevant code:

4. Deploy with verifiable health and configuration

The production API runs on Render with Supabase PostgreSQL and Supabase Auth. The /health endpoint performs a database connectivity check, not merely a process liveness check. Render uses that path for deployment health verification.

Production configuration uses:

For Supabase’s Transaction pooler, the database engine disables asyncpg prepared-statement caching. That setting matters because pooled transaction-mode connections do not support session-scoped prepared statements.

The deployment also retains a clear migration story: startup runs Alembic migrations, while production release practice should treat migrations as an explicit release step.

Relevant documentation:

5. Make mobile integration unambiguous

The mobile handoff avoids localhost ambiguity:

Mobile devices cannot reach a development machine’s 127.0.0.1; the case-study documentation explicitly calls out LAN addresses or tunnels for local device testing. Clients are instructed to clear stored tokens on 401 and return to Supabase Auth, rather than retrying indefinitely with an invalid credential.

Stack

Results

Define failure drills explicitly

Production readiness can be reviewed as a set of failure drills:

Those checks convert deployment documentation from a narrative into repeatable operational behavior. They also give a hiring reviewer a practical way to validate the platform claims without deploying production infrastructure.

Lessons

  1. Invalidation is part of the feature. A cache without tested mutation paths is a future stale-data bug.
  2. Health checks should test dependencies. A process can be alive while its database is unreachable.
  3. Scope everything by user. User isolation applies to primary records and derived caches alike.
  4. Deployment docs are product docs. A stable URL, health path, auth contract, and token-handling rules prevent most integration mistakes.
  5. Document what is not built. Request-driven caching, permissive development CORS, and missing schedulers should be explicit technical debt rather than surprises.
  6. Keep analytics explainable where possible. Rule-based budgets complement ML forecasts by giving users an auditable answer alongside a probabilistic one.

Part of the "Expense Tracker Case Studies" series