# The dashboard

> What each page of /sailfish shows, and the two gates that decide who sees it.

Source: https://boring-observability.dev/sailfish/docs/dashboard
Section: Using Sailfish — Sailfish documentation
Updated: 2026-10-02

---

The dashboard lives at `/sailfish`. It is self-contained (Blade, Alpine and uPlot, served by the package itself), so there is nothing to build or publish for it, and it runs under a Content-Security-Policy without `'unsafe-eval'`. Who can open it is up to the gates described in [installation](https://boring-observability.dev/sailfish/docs/installation#gate).

Every rate on it is what moved over the seconds the snapshots cover, never a raw delta. After a gap, one snapshot covers hours, and its rows are spread over them rather than drawn as one spike.

## Overview

Open events, rows read through an index against rows read by full scans, the five most scanned tables, and markers on the charts for MySQL restarts and schema changes. This is the page to open after a deploy.

## Server

Connections against `max_connections`, statements, time waiting for row locks, buffer pool misses, temporary tables and sorts spilling to disk, and InnoDB's history list. It also shows the buffer pool's size against the data being watched, which answers whether the working set still fits in memory.

## Activity

Read live when you open it, and never stored. It shows who is blocking whom, as trees from the session everyone waits for, over row locks and table metadata locks. The classic case is an `ALTER TABLE` stuck behind an idle transaction, with every query on that table queued behind the `ALTER`. It also lists open transactions oldest first, flagging those idle in a transaction, and the statements running now.

It needs nothing beyond `SELECT` on `performance_schema`. Statements are shown with each literal replaced by `?` unless the viewer passes the `viewSailfishQueryText` gate.

## Indexes

Every index with its status, its last use, its size, its columns and 30 days of reads and writes. The status is one of:

| Status | Meaning |
| --- | --- |
| hot | Last fetched within the last 7 days |
| cold | Fetched before, but not in the last 7 days |
| never used | No fetch in the history Sailfish has |
| dropped | Gone from the schema, kept with its history |

PRIMARY and unique keys are hidden until you ask for them: they enforce a constraint, so "unused" means little. Each index has a page with its full history and the indexes that cover it, and a redundant one shows how to drop it.

## Tables

Rows fetched through an index against rows scanned, over time and broken down by index, with the time spent waiting for table locks. Size and row count are read once a day and charted beside them.

## Errors

Errors the server raised over time, the most frequent, and when each was first seen. Deadlocks (1213), lock wait timeouts (1205) and duplicate keys (1062) are pointed out. Errors are counted server-wide, not per schema.

## Events

The full record of every [event](https://boring-observability.dev/sailfish/docs/events), open and resolved, filterable by type. This is where an event is acknowledged, which stops its reminders, or muted until a date or for good. Detectors still waiting for enough history say here how many more days each one needs.
