DEV Community

Roberto Luna
Roberto Luna

Posted on

Optimizing Next.js TV Dashboard Refresh to Preserve Neon Scale‑to‑Zero

Optimizing Next.js TV Dashboard Refresh to Preserve Neon Scale‑to‑Zero


TL;DR:

I bumped the TV dashboard auto‑refresh interval from 30 s to 15 min in src/features/tv/TVDashboard.tsx. This change frees up Neon compute resources and prevents unnecessary scaling events, keeping the database in a low‑cost state.


The Problem

Neon, our Postgres‑as‑a‑service provider, scales compute resources up and down automatically. With the TV dashboard polling the database every 30 seconds, the DB stayed “warm” all the time, consuming compute credits even when the data was static. The symptom was a spike in Neon compute usage and a higher bill, without any functional benefit.

ERROR: Neon compute headroom exceeded
  - Frequent polling prevented scale‑to‑zero
Enter fullscreen mode Exit fullscreen mode

What I Tried First

  1. Leave the 30 s interval unchanged – no improvement, compute still stayed active.
  2. Reduce to 5 min – still caused occasional scaling up because the refresh triggered a new connection each cycle.
  3. Add a debounce in the query layer – added complexity without addressing the root cause of the polling frequency.

The root issue remained: the UI kept re‑fetching data too often for a data source that changes only on manual sync.


The Implementation

1. Update the refresh constant

In src/features/tv/TVDashboard.tsx, the polling interval was originally set to 30 seconds:

// src/features/tv/TVDashboard.tsx
const REFRESH_MS = 30_000; // 30 s
Enter fullscreen mode Exit fullscreen mode

I first bumped it to 5 minutes:

const REFRESH_MS = 300_000; // 5 min
Enter fullscreen mode Exit fullscreen mode

But to give Neon more headroom, I then increased it further to 15 minutes:

const REFRESH_MS = 900_000; // 15 min
Enter fullscreen mode Exit fullscreen mode

The final diff looks like this:

-const REFRESH_MS = 30_000;
+const REFRESH_MS = 900_000; // 15 min
Enter fullscreen mode Exit fullscreen mode

2. Use the constant in the polling effect

The component uses useEffect with setInterval to re‑fetch TV data:

useEffect(() => {
  const interval = setInterval(() => {
    fetchTvData(); // async call to API/DB
  }, REFRESH_MS);

  return () => clearInterval(interval);
}, []);
Enter fullscreen mode Exit fullscreen mode

With the new REFRESH_MS, the interval now triggers only every 15 minutes, drastically reducing the number of database connections.

3. Add documentation on the change

To keep the team informed, I added two markdown files in the repo root:

  • CLAUDE.md – a high‑level incident recap and architecture overview.
  • CLAUDE_CODE_CONTEXT.md – a snapshot of system status, including the updated refresh interval.

These docs help anyone reviewing the repo to understand why the change was made and its impact on Neon.


Key Takeaway

When polling a serverless database, set the refresh interval to the minimal frequency that still satisfies UX.

A 30 s interval can keep a database “warm” unnecessarily, while a 15 min interval can preserve compute headroom without hurting user experience. Always audit your polling logic against the database’s scaling model.


What's Next

  1. Move to server‑sent events – Replace polling with a WebSocket or SSE channel that pushes updates only when data changes, eliminating any idle queries.
  2. Centralize refresh config – Store REFRESH_MS in a .env file so that it can be tuned per environment (dev, staging, prod).
  3. Monitor Neon metrics – Add a small dashboard that visualizes compute usage over time to catch similar issues early.

vibecoding #buildinpublic #nextjs #react #neon #serverless #devops #typescript


Part of my Build in Public series — sharing the real process of building SaaS projects from Playa del Carmen, México.

Repo: zaerohell/pcview · 2026-08-03

#playadev #buildinpublic

Top comments (0)