---
title: "Read the scheduler's lossy transition-queue counters (admin only)"
method: GET
path: "/api/v1/admin/scheduler/transition-drops"
tags: ["Admin"]
---

# Read the scheduler's lossy transition-queue counters (admin only)

`GET /api/v1/admin/scheduler/transition-drops`

## Request

- Base URL: `https://api.uptimemonitoring.com`
- URL: `https://api.uptimemonitoring.com/api/v1/admin/scheduler/transition-drops`
- Auth: HTTP bearer

Returns three cumulative, process-lifetime counters tracking
the scheduler's internal transition-enqueue path (issue #103),
plus the timestamp the counters started from. Requires admin
role per the same `auth.RequireAdmin` middleware that gates
`/api/v1/admin/ping`.

As of issue #377's lossless, retried transition queue, `overflow`
and `flap_exit_deferred` are retained for wire compatibility only
and always read zero — the shard-full and flap-exit-deferred
conditions they used to count no longer exist (the per-shard
queue is unbounded, and enqueuing a transition never fails).
`writer_error` now counts only a PERMANENT RecordStateTransition
failure (a data-exception or integrity-constraint-violation
SQLSTATE, or an invalid revision) — a transient failure, including
an ambiguous commit outcome, is retried against the same job
instead of being dropped, so it never increments this counter.

The dispatcher additionally fires a `scheduler_transition_dropped`
security-rail alert (see `SECURITY_ALERT_WEBHOOK_URL` in
`CLAUDE.md`) for `writer_error`, rate-limited to at most one
alert per rolling 10-minute window — a burst lasting longer than
10 minutes fires again once that window elapses. Each alert's
payload carries the three counters' process-lifetime totals as
of the triggering occurrence, not the size of any completed
burst. This endpoint is the read-only complement for ad hoc
polling or dashboards, not a substitute for that alert.

Counters reset to zero only on dispatcher restart; `since`
reports the process instant they started counting from, not a
rolling window.

## Response `200`

Current transition-drop counters.

- TransitionDropsStatus
  - `overflow` integer, required: Always zero (issue #377). Retained for wire compatibility only: the per-monitor writer shard used to be a bounded channel that could fill at enqueue time, dropping the transition. It is now an unbounded, retried queue — nothing is ever dropped for being full.
  - `writer_error` integer, required: Cumulative count of transitions dropped because RecordStateTransition failed with a PERMANENT error (issue #377) — a data-exception or integrity-constraint-violation SQLSTATE, or an invalid revision. A transient failure, including the ambiguous "commit outcome unknown" case, is retried against the same job instead of being dropped, so it never increments this counter.
  - `flap_exit_deferred` integer, required: Always zero (issue #377). Retained for wire compatibility only: flap-decay exits used to be deferred when the writer shard was full; the queue is now unbounded, so there is nothing left to defer.
  - `since` string, date-time, required: Process instant the three counters started at zero (dispatcher start), not a rolling window.

## Other responses

- `401`: Missing or invalid credentials.
- `403`: Authenticated but not an admin.
- `429`: Per-account dispatcher rate limit exceeded (200 requests/minute). The `Retry-After` header gives the integer seconds until at least one token has refilled. The `X-RateLimit-*` trio reflects the bucket whose rejection produced this response — usually the global 200/min cap; on `POST /api/v1/monitors` a 429 may instead reflect the per-route 20/min creation limit.

---

[API](https://skmtc.dev/uptimemonitoring/apis/uptimemonitoring-com-api.md) · [All operations](https://skmtc.dev/uptimemonitoring/apis/uptimemonitoring-com-api/llms.txt) · [OpenAPI document](https://skmtc.dev/uptimemonitoring/apis/uptimemonitoring-com-api/revisions/ddcb2a8bc70f?raw)
