Why my Next.js dashboard was always showing stale data — and the one-line fix

Published: (March 23, 2026 at 10:41 PM EDT)
3 min read
Source: Dev.to

Source: Dev.to

Overview

The timestamp was updating. The AI recommendations kept coming in. Everything looked alive.

But the sensor values hadn’t moved in twenty minutes.

That’s the kind of bug that gets inside your head. Half the app was working perfectly, which meant the problem wasn’t obvious—it was hiding somewhere in the middle.

SensorWatch AI is an industrial sensor‑monitoring dashboard built with Next.js 14, TypeScript, PostgreSQL, and an LLM integration via OpenRouter. It simulates three industrial sensors, performs real‑time anomaly detection, and generates maintenance recommendations in natural language. On paper it was fine—until it wasn’t.

Everything I tried that didn’t work

The AI hypothesis

OpenRouter’s free tier can be painfully slow. I suspected a race condition between the sensor simulation and the anomaly analysis, so I split the AI call and the sensor simulation into two independent Promise.all flows. The bug persisted.

Front‑end guesses

I wondered whether a useCallback wasn’t re‑executing because of missing dependencies. Adding more console.logs didn’t reveal anything.

The breakthrough

After scattering console.logs everywhere, I discovered that the database was returning exactly the same data on every request—same values, same timestamps. The sensors were still generating new readings; the data simply wasn’t being fetched correctly.

The cause

The problem lived in a single line of the Prisma query:

const readings = await prisma.sensorReading.findMany({
  where: { sensorId: sensor.id },
  orderBy: { createdAt: "asc" }, // ← wrong direction
  take: 50,
});

orderBy: { createdAt: "asc" } asks for the oldest 50 records. With thousands of rows in the table, those oldest entries never change, so every request returned the same stale slice of data. The UI appeared alive because timestamps were generated client‑side with new Date(), and the AI endpoint used a correctly ordered query.

The fix

const readings = await prisma.sensorReading.findMany({
  where: { sensorId: sensor.id },
  orderBy: { createdAt: "desc" }, // newest first
  take: 50,
  select: {
    value: true,
    isAnomaly: true,
    createdAt: true,
  },
});

// Reverse so the chart displays time left‑to‑right
const sortedReadings = readings.reverse();
  • desc fetches the 50 most recent records, which change with each simulation cycle.
  • .reverse() puts them back in chronological order for the chart (oldest on the left, newest on the right).

Updating the status cards becomes straightforward:

currentValue: sortedReadings[sortedReadings.length - 1]?.value ?? null,
currentIsAnomaly: sortedReadings[sortedReadings.length - 1]?.isAnomaly ?? false,

The lesson

When something isn’t displaying correctly, verify the data before touching the UI.

I spent hours chasing symptoms in the frontend, AI pipeline, and fetch logic, while the root cause was a single misplaced asc. A single console.log at the API response level would have shown the identical payload on every request and saved a lot of time.

Check your data first. Then your code.

SensorWatch AI is open source — github.com/RonaldGGA/sensorwatch-ai
Live demo: sensorwatch-ai.vercel.app

0 views
Back to Blog

Related posts

Read more »

Understanding Next.js Cache (Part 5)

If you have built an application using the Next.js App Router, there is a 100 % chance you’ve come across the issue of updating the database but the page still...