See the slow query. Not the stack trace.
Spool attaches a span to every SQL statement your service runs — so a 1.4s endpoint is one click from the exact query, its plan, the lock it waited on, and the deploy that regressed it.
Everything your DBA checks by hand, attached to the request.
Auto-instrumentation, the bound plan, lock waits, and N+1 detection — wired to the same trace context as your HTTP spans. One install, no agent, no sampling guesswork.
The EXPLAIN you never have to re-run.
Spool captures the planner output with the live bind parameters, so the plan you read is the plan that ran — slow rows highlighted, scan types flagged.
-- bound params: order_id = 90412 SELECT o.*, li.sku, li.qty FROM orders o JOIN line_items li ON li.order_id = o.id WHERE o.id = $1; Nested Loop (rows=1 width=212) -> Index Scan on orders (0.04ms) -> Seq Scan on line_items (1041ms) Filter: order_id = $1 · 4.2M rows scanned Suggested: CREATE INDEX ON line_items(order_id)
Find the 240-query loop.
Spool collapses repeated statements within a trace and tells you which line of code fanned them out.
See who held the row.
Every block records the blocking PID, the lock mode, and the statement that held it — no pg_locks archaeology.
Three lines.
// auto-patches pg + prisma import { spool } from "@spool/node"; spool.init({ service: "api" });
Already speaks your stack.
Page on the deploy. Skip the noise.
Spool diffs each query's P95 across deploys and routes a regression to the exact commit — high-severity to PagerDuty, the rest to Slack.
Rank every query by the time it actually costs you.
Spool groups statements by their normalized shape, then sorts by total DB time — not call count. The query firing 4 times an hour at 1.2s outranks the one firing a million times at 0.4ms, because it's the one burning your latency budget.
- Normalized fingerprinting — $1 and $2 fold into one row, literals stripped.
- Drill from a query to the 50 slowest traces that ran it, sampled tail-first.
- Compare two deploys side-by-side — every query's P50/P95/P99 delta.
- Native OpenTelemetry — your Grafana and Datadog taps keep working.
Pay per span. Not per host.
A span is one instrumented statement. Bundles roll over for 90 days. No agent license, no per-seat tax on the engineers reading the traces.
Hobby
free foreverFor a side project or one service in staging.
- 1,000,000 spans / mo
- 3-day trace retention
- Bound plan capture + N+1
- Community Discord
Team
incl. deploy diffingFor teams shipping a Postgres-backed product to real traffic.
- 250,000,000 spans / mo
- 30-day retention + deploy diffing
- Lock-wait + regression alerts
- Slack + PagerDuty + GitHub Checks
- SLA: P95 ingest < 2s
Scale
BYOCFor regulated workloads and 10B+ spans a month.
- Bring-your-own-cloud ingest
- SOC 2 Type II + HIPAA + SCIM
- Query-text redaction at the agent
- Solution architect + 1h SLA
Engineers who got tired of guessing which query.
"Spool found a Seq Scan that had been hiding behind a 200 OK for fourteen months. Adding one index cut our P95 checkout from 1.4s to 90ms."
"The deploy diffing is the feature I didn't know I needed. Every PR now shows me which query its migration made 40% slower before it merges."
"We dropped two APM agents and our log bill in half. Spool's per-span price means we finally trace 100% of traffic instead of sampling 5%."
Questions a senior engineer asks.
Everything else is in the docs. The SDK is open source under Apache-2.0 — read exactly what it patches before you install it.
What's the per-query overhead of auto-instrumentation?+
We wrap the driver's submit path, not the protocol. Measured overhead is P50 28µs, P99 71µs per statement — captured plans are fetched out-of-band from a sampled tail, never on your request path.
How is a "span" defined for billing?+
One executed statement = one span, regardless of rows returned. A transaction with 6 statements is 6 spans. We bill in $0.0061-per-1M increments and bundles roll over month-to-month for 90 days.
Can I redact query text and parameters before they leave my VPC?+
Yes. On Scale, the collector normalizes statements and strips literals at the agent — only the fingerprint and timing leave your network. Bind parameters are hashed locally and never transmitted.
How do you capture EXPLAIN without doubling my query load?+
We only run EXPLAIN (ANALYZE, BUFFERS) on tail-sampled slow statements — by default the slowest 0.5% over 200ms, capped at 4 per query shape per minute. Never on the hot path.
Does it work with PgBouncer in transaction-pooling mode?+
Yes. Spool instruments above the pooler at the driver level, so trace context survives connection multiplexing. We carry the trace ID in an application_name tag so it correlates with pg_stat_activity too.
Install it before lunch. Find the slow query by 2pm.
Free up to a million spans a month, no credit card. Three lines, no agent, no sampling config.