all work

Nimbus Analytics

(SaaS Dashboard)

A multi-tenant analytics dashboard that turns raw product events into answers in under a second.

  • −45% load time
  • 12k weekly users
  • 99.95% uptime

2025 · Next.js · tRPC · PostgreSQL · Redis · AWS

nimbusanalytics.app

Problem

(what hurt)

Customers exported CSVs every Monday, rebuilt the same charts by hand and still argued about which numbers were right. Queries against the raw events table took 8–14 seconds and timed out on large accounts.

Project goal: Product teams at 300+ companies were drowning in CSV exports. They needed a real-time analytics dashboard that answers everyday questions in under a second, with no data team in the loop.

Architecture

(how it fits together)

Events stream into Postgres through a queue, where hourly materialized views pre-aggregate the heavy metrics. A tRPC API reads from a Redis cache with 60-second TTLs and falls back to the views, so page loads never touch raw events.

Tech decisions: Next.js for SSR and streaming, tRPC for type-safe APIs end to end, and a Redis cache in front of Postgres materialized views to cut response time. Hosted on AWS with per-tenant rate limits.

  • Next.js
  • tRPC
  • PostgreSQL
  • Redis
  • AWS
(architecture)Next.jstRPC APIPostgresRedis
server/routers/metrics.ts
export const metricsRouter = router({
  overview: protectedProcedure
    .input(z.object({ range: z.enum(["7d", "30d", "90d"]) }))
    .query(async ({ ctx, input }) => {
      const key = "overview:" + ctx.org.id + ":" + input.range;
      const cached = await redis.get(key);
      if (cached) return JSON.parse(cached);

      const data = await db.metrics.aggregate(ctx.org.id, input.range);
      await redis.set(key, JSON.stringify(data), "EX", 60);
      return data;
    }),
});

Features

(what it does)

  • Type-safe from database to chart

    One schema drives the database, the API and the React components, so a renamed column breaks the build, not production.

  • Streaming dashboards

    Server Components stream each widget as soon as its query resolves, so the page is useful before it's finished.

  • Shareable snapshots

    Any view can be frozen into a public, read-only link with its own cache key.

(in use)
ship it ✓
nimbusanalytics.app/settings

Challenges

(what was hard)

  1. 01Noisy neighbours

    One huge tenant could slow down everyone else. Per-org rate limits and query budgets kept p95 flat during spikes.

  2. 02Cache invalidation

    Short TTLs plus event-driven cache busting on writes kept data fresh without hammering Postgres.

Results

  • −45% load time
  • 12k weekly users
  • 99.95% uptime

Median dashboard load dropped from 3.1s to 1.7s, tickets about wrong numbers fell by two thirds, and the product now serves 12k weekly users.

design & code by Shreya Pathak