query-design
Design or review SQL reads, writes, scans, backfills, and slow database paths.
Skill by joelhooks
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/joelhooks-query-design-6a4293
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: design, backend
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/query-design
What's inside
- Skill name
query-design- Description
- Design or review SQL reads, writes, scans, backfills, and slow database paths. Use before changing a store method or any loop that queries. Covers round-trip arithmetic, batching, keyset paging, index evidence, row budgets, PlanetScale Vitess limits, Hyperdrive connections, statement-count tests, and statement-template fences.
- License
- MIT
- Instructions
- 155 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Design queries around round trips
Count round trips before writing SQL. Small tables can still produce slow runs when each row needs several database calls.
```text
round trips per call × calls per run × RTT = wall time
```
RTT means round-trip time. This arithmetic estimates serial network time; query execution, decoding, and connection acquisition add costs.
Consider an illustrative scan of about 9k threads:
- Per-thread reads: 5 round trips × about 9.3k threads × 81 ms ≈ 63 minutes.
- Paged and batched reads: 2 round trips × 93 pages × about 100 ms ≈ 20 seconds.
- These are planning inputs. Measure RTT where the caller runs before choosing its budget.
A [capability](/systems/capabilities) call has a constant round-trip budget, independent of result size. State that number and bound its result. A scan costs O(pages), never O(rows). Count transaction control statements and any final empty-page probe too.
Done means the store implementation matches a written query plan, and checks detect violations of its statement and access-path budgets.
## 1. Name the question, caller, and rate
Record these before changing the store:
- **Question**: The fact or change the caller needs
- **Caller**: Capability, scan, export, or background job
- **Rate**: Calls per invocation and invocations per second or run
- **Authority**: System of record, derived copies, and writer
- **Row budget**: Maximum rows read with tables at 100× today's size
- **Statements**: Round trips per call, per page, and per run
- **Timing**: Measured RTT, predicted wall time, and observed page time
- **Concurrency**: Maximum simultaneous queries or transactions
Measure table sizes and inspect existing indexes. Keep credentials and row contents out of measurements and reports. Route operator, export, and monitor reads to a replica or a copy. Record any consistency tradeoff. Compare repeated joins or aggregates with a keyed [read model](/skills/add-a-store) before adding a hot-path scan.
## 2. Apply the shared rules
1. **Never query inside a loop over rows.** Page parents, fetch their children with one batched `IN`, then join in memory. Apply the same authorization filter to both queries. Keep analysis pure over the fetched rows. Bound child fan-out and result bytes too. Page children separately when one parent can exceed the batch budget.
2. **Use keyset paging, never OFFSET.** Order by an indexed tuple that ends in a unique column. Match the cursor predicate to each column's sort direction. Fetch `limit + 1` to detect another page. Emit a cursor from the last returned row. Exclude the extra probe row from the returned page.
3. **Name each query's index and prove it with EXPLAIN.** Use representative data and the actual query builder. Record the chosen `key`, access `type`, estimated `rows`, and sorting work for MySQL. Expect `const`, `eq_ref`, `ref`, `range`, or an index-ordered limit that meets the row budget. Equivalent plan fields apply to other engines. Inspect examined rows when the engine supports execution analysis. Fix full scans or filesorts on growing tables. Justify any index hint with plan evidence.
4. **Select only columns the caller uses.** Keep large bodies, JSON, and text fields out of counts and metadata scans.
5. **Keep transactions short.** Name the atomic writes or consistent reads that require one. Never wrap an entire scan in a transaction. Keep external I/O outside the transaction.
6. **State a concurrency bound.** Start production scans with serial pages over one connection. Measure before adding parallelism. Explain the load budget and why more concurrent work helps.
7. **Show progress on long runs.** Emit phase, completed pages, counts, and elapsed time to stderr. Use counts-only output. Set a measured stall deadline and return a typed failure with phase and completed count.
8. **Use a store boundary.** A [port](/lore/hexagonal-architecture) declares the operations that callers need. An [adapter](/lore/hexagonal-architecture) implements those operations for a provider. A [Layer](/lore/layers-make-dependencies-explicit) builds services and supplies their construction dependencies. Follow [add-a-store](/skills/add-a-store) for job-shaped operations and adapter Layers. Keep SQL, Drizzle, connection pools, and driver calls inside the adapter. Callers depend on the port.
A result limit bounds returned rows. EXPLAIN evidence must also prove the scanned-work budget. For tenant-scoped MySQL stores, lead the supporting index with the tenant key and preserve that filter throughout paging.
## 3. Check PlanetScale Vitess limits
These limits apply to PlanetScale Vitess transactional workloads. They do not describe PlanetScale Postgres. The [Vitess system limits page](https://planetscale.com/docs/vitess/troubleshooting/planetscale-system-limits) supplies the published values.
- **Transaction timeout**:
- Published value: 20 s
- Design consequence: Treat it as fixed in application configuration. Use short transactions.
- **Autocommit query timeout**:
- Published value: 900 s
- Design consequence: Page work well before the timeout.
- **Rows returned, updated, or deleted per query**:
- Published value: 100k
- Design consequence: Bound reads and bulk writes.
- **Result size per query**:
- Published value: 64 MiB
- Design consequence: Bound bytes as well as rows.
- **Transaction pool**:
- Published value: Capped; capacity varies by instance type
- Design consequence: Limit simultaneous transactions and keep them short.
The limits page says support can sometimes adjust limits per database. It offers no application setting for the transaction timeout. Do not make a design depend on a larger timeout.
Map a killed transaction to a typed adapter failure. Preserve the operation, provider code, and redacted cause. An error containing `1105` and `context deadline exceeded` needs timeout handling; `1105` alone is a generic error code. The [errors page](https://planetscale.com/docs/vitess/troubleshooting/errors) also documents `2013` deadline errors and `1105` transaction-aborted timeout errors.
Vitess pools MySQL connections through vttablet. `SHOW PROCESSLIST` shows those pool connections, rather than a one-to-one application-session list. Use application-side timing and provider query diagnostics to inspect a stalled run.
## 4. Keep Hyperdrive connections request-scoped
For the shared MySQL path, use mysql2 text-protocol `.query()` inside the adapter, as drovr does. Keep that protocol choice explicit in the query runner. Count every statement it sends.
Create the connection within the Worker request and reuse it for that request's statements. Release it through the request lifecycle. Hyperdrive owns reuse of underlying database connections across requests. Avoid a second pool or a module-global driver connection. See [Cloudflare's MySQL example](https://developers.cloudflare.com/hyperdrive/examples/connect-to-mysql/) for connection lifetime details.
## 5. Make checks stronger than prose
### Count statements through the real store
Use `it.effect` and a counting executor Layer at the adapter boundary. The executor port describes statement execution; its test wrapper counts calls while delegating to the real fixture executor. Keep counters scoped to each test. Exclude fixture setup from the measured call count. This is pseudocode for a consumer-owned port, rather than a shipped rat-stack MySQL API:
```text
it.effect("scan obeys its statement budget", Effect program):
generate N parents and bounded children
seed the native database fixture
provide the real store with a counting executor Layer
reset the statement counter after setup
scan all pages through the store port
verify complete results, ordering, and authorization filters
assert statements <= planned statements per page × page count
+ planned fixed overhead
```
Generate cases below, at, and above page boundaries. Include empty pages and parents with different child counts. Vary parent count within one page: its statement count must remain constant. Include cases where the planted N+1 exceeds the budget.
Replace the batched child read with one query per parent. The count test must fail. Restore batching and run it again. Record both outcomes before trusting the check. Check rows and bytes separately; a statement-count test cannot prove index use or bounded child fan-out.
### Commit statement templates and enforce a plan fence
A fence is an enforced check that rejects prohibited work. A handler is the server-side implementation of an action. A stronger check records every statement template the native suites issue, with its source site and exercising handler. Normalize placeholder-list lengths in `IN` and multi-row `VALUES`. Never record parameter values.
```text
committed manifest entry:
template: normalized statement text
sites: source locations that issue it
handlers: named handlers that exercise it
sentBy: Worker | operator | fixture | diagnostic
executor plan fence:
normalize each application statement
fail when its template is absent from the manifest
fail when its source or execution surface is disallowed
inspect each query's plan against its index and row budgetFrom joelhooks/rat-stack, MIT.
More from joelhooks/rat-stack
- 0.684score
rat-stack-mode
joelhooks
Route non-trivial rat-stack code, data, design, investigation, and documentation tasks to every matching playbook and principle.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
investigate-a-failure
joelhooks
Find the cause of a crash, wrong output, flaky test, or slow run with evidence, fix it at its source, and leave a notebook a person can learn from.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
uncomplect
joelhooks
Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that…
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
profile-a-worker
joelhooks
Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof.
SkillAFreshness: A★ 129Claude Code +9 - 0.681score
ship
joelhooks
Learn how to ship a change through merge, CI, release, stage deployment, rollout, verification, rollback and flags.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
add-a-store
joelhooks
Add persistence through a service named for an application job, with validation, vendor Layers, migrations, bounded reads, and shared backend tests.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
gardener
joelhooks
Keep rat-stack current and clean.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
learn
joelhooks
Present Effect, Alchemy, XState, and application-design concepts during real work when the operator enables learn mode.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
find-peers
joelhooks
Refresh public peers, exact stack versions, and usefulness tiers every week or two and after each shared dependency update.
SkillAFreshness: A★ 129Claude Code +9 - 0.676score
add-a-capability
joelhooks
Learn how one contract and its handler become a command, HTTP route, MCP tool, browser RPC, and sandbox call.
SkillAFreshness: A★ 129Claude Code +9 - 0.676score
add-a-lifecycle-machine
joelhooks
Learn how XState owns a lifecycle while Effect owns its work, errors, and services.
SkillAFreshness: A★ 129Claude Code +9 - 0.676score
learn-alchemy
joelhooks
Learn how Alchemy 2 turns an Effect program into a planned Cloudflare deployment.
SkillAFreshness: A★ 129Claude Code +9
Signals
- Stars
- 129
- Forks
- 8
- Open issues
- 2
- Last commit (this folder)
- Oct 24, 2026 (4 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/joelhooks/rat-stack
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
Same skill elsewhere
Copies of this SKILL.md published by others; search shows only one of them.
More from joelhooks
- 0.684score
rat-stack-mode
joelhooks
Route non-trivial rat-stack code, data, design, investigation, and documentation tasks to every matching playbook and principle.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
uncomplect
joelhooks
Find responsibilities that a rat-stack design combines, separate them into capabilities, cartridges, machines, features, and clients, and enforce that…
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
investigate-a-failure
joelhooks
Find the cause of a crash, wrong output, flaky test, or slow run with evidence, fix it at its source, and leave a notebook a person can learn from.
SkillAFreshness: A★ 129Claude Code +9 - 0.682score
profile-a-worker
joelhooks
Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof.
SkillAFreshness: A★ 129Claude Code +9 - 0.681score
ship
joelhooks
Learn how to ship a change through merge, CI, release, stage deployment, rollout, verification, rollback and flags.
SkillAFreshness: A★ 129Claude Code +9 - 0.679score
add-a-store
joelhooks
Add persistence through a service named for an application job, with validation, vendor Layers, migrations, bounded reads, and shared backend tests.
SkillAFreshness: A★ 129Claude Code +9
Cite this page
query-design skill. Agent Mart. https://agentmart.dev/skills/joelhooks-query-design-6a4293 (last updated 2026-10-24)