---
title: "The COUNT(*) behind every hover label on the admin console"
canonical: https://dxdev.com/blog/25-second-admin-screen/
datePublished: 2026-04-17
---
The admin console view for recent signups took roughly 25 seconds to render a list of about 15 rows in the observed environment. Support staff used it as a daily starting point, so that latency was unacceptable for the task.

We opened the ticket expecting a layout fix. The title said responsive design and the file it pointed at was the admin console template. Then we loaded a profiler trace to see what was actually executing, and the first thing in it was the new signups section resolving through a `FULL OUTER JOIN` against the session log table.

## The join was doing work the view never asked for

The session log table recorded high-volume activity over time. For the recent-signups screen, the trace showed the join doing more than the view required. The customer table already held the signup-date field, which made it the more direct source for this display, once the team verified the business definition of a recent signup.

Above the new accounts list, the summary widget had a different problem. It ran unbounded `COUNT(*)` queries to populate tooltip labels on hover. No date range, no scope, nothing limiting the count to a recent window. On every admin console page load, the widget asked the database to count the full contents of several tables and embedded those numbers in labels that appear when a user hovers and disappear when they move away. The count was never wrong. It had no business being recalculated on every page load to power a tooltip.

Feature debt like this builds up as data volume and usage change. A count that was acceptable at an earlier scale may no longer justify its cost, especially when the value only shows up in a low-priority UI detail. The link between a hover label and page latency is easy to miss until you measure.

## What the fix required

The rewrite of the new signups query stopped using the session log table as the source. It now pulls directly from the customers table with a filter on the signup-date column. The admin console does not need session history to show who signed up recently. It needs to know when they signed up. After the rewrite, the observed view time dropped from roughly 25 seconds to about 500 milliseconds on the same test data. That result is specific to the measured environment and query shape, and says nothing about other implementations.

For the summary widget, the fix was to stop computing the count on demand. You can cache it or drop it from the tooltip entirely, depending on whether the tooltip is worth keeping. Here it wasn't, so it went. The table structures and the server were fine. The queries were doing more than the screens required, and nobody had traced the latency back to the SQL causing it.

The production app is an older web application. The admin console has accumulated queries that made sense on smaller tables and have gotten slower since. Finding them means running the queries and measuring them. Reading the code and guessing won't get you there. A slow page is the signal, and the profiler trace is the map.

## Handing diagnostics the right evidence

An AI assistant is more useful when it can inspect the same safely scoped evidence as the reviewer. That does not justify sharing a personal administrator login, persisting a privileged session cookie, or granting broad production access.

For a sensitive admin workflow, use a dedicated least-privilege account, a sanitized staging environment, [scoped read-only access where possible](/everyday-ai/read-before-write/), short-lived credentials, and audit logging. If those controls aren't available, hand over carefully redacted traces, screenshots, query plans, and representative test data instead of bypassing access boundaries for convenience.

AI assistance can speed up inspection and rewrite work, but it can't replace the evidence that identifies the expensive operation. Without the trace and plan, a suggested layout fix would have answered the ticket description and left the measured latency alone. The input that mattered was the profiler evidence, read against what the screen actually needed.

## What we left unaudited

We did not audit the rest of the admin console during this ticket. Several other paths run similar aggregates on tables that have grown past the point where those aggregates are cheap, and we don't have numbers for all of them. What we do know is that the `COUNT(*)` in the summary widget ran on every page load, for every admin console user, against unscoped table counts, to power a tooltip.

A slow internal page can come from query shape, indexing, data volume, application work, network behavior, or several of those together. Here, the trace showed queries answering a broader question than the screen required. When an internal screen is slow, ask for the profiler trace and query plan before approving a fix based on the ticket's description. This one was filed as a layout ticket and hid a join against the wrong table plus unbounded counts on every page load.
