# The SQL query approval workflow, explained

> What a query approval workflow is, the states a request moves through, who approves what, and the failure modes worth designing against before you build one.

- Updated: 2026-10-10
- Source: https://queryproxy.com/sql-query-approval-workflow/
- Language: en-US
- Author: Muhammet Şafak

---
A query approval workflow replaces "run it and hope" with "submit it and have
someone look". The developer writes SQL but does not execute it; a second person
reviews the statement; the system runs it on the developer's behalf and returns a
controlled result. The developer never holds the credential.

## The states a request moves through

**Submitted.** A developer writes a statement against a connection they have been
granted. Nothing has run.

**Guarded.** The system parses the SQL before any human sees it. This is machine
work: reject `UPDATE` and `DELETE` with no `WHERE` clause, inject a `LIMIT` into an
unbounded `SELECT`, block administrative statements. Catching these automatically
means reviewers spend their attention on intent rather than on syntax.

**Pending.** The request waits for a decision, visible to the people who can make
one. If it waits somewhere nobody looks, the workflow has already failed.

**Approved or rejected.** A reviewer decides, and either outcome is recorded with
who decided it and when.

**Executed.** The system connects and runs the statement. Because the wait is
unbounded, this belongs on a worker rather than in a web request.

**Returned.** Results come back limited, masked, and stored under a retention
rule — then written to an audit log.

## Failure modes worth designing against

**Approval fatigue.** A reviewer facing forty requests approves all forty without
reading them. Guards help by rejecting the obviously wrong before a human is
involved, so what reaches a person is worth reading.

**The workflow nobody uses.** If approval is slower than the bastion host still
sitting there, people use the bastion. Either the approval path becomes the fast
path, or the alternative closes.

**Self-approval.** A workflow where reviewers can approve their own requests is a
logging system wearing a workflow's clothes. Enforce it in code, and make any
exception — such as an administrator override — visible in the audit trail.

**Unbounded results.** An approved `SELECT` over a hundred million rows is an
approved outage. Cap it, and stream rather than buffer.

**Approval as the only control.** Approval decides whether a statement runs. It
does nothing about what comes back. Without masking, an approved query still puts
unmasked PII on someone's laptop.

## How QueryProxy implements it

QueryProxy is this workflow as a product. Requests are submitted in a guarded
editor, parsed by an AST inspector before review, and shown to DBAs in a web
queue and as [chat cards](/blog/approve-sql-queries-in-slack-teams/) — Approve and Reject buttons in Slack, and in Teams a
card that announces the request and links to it, with the decision made by an
automation (for example a Power Automate flow) calling an HMAC-signed action
endpoint — so the decision happens where the reviewer already is. Self-approval is blocked in
code; an administrator can override it, and the override is flagged in the audit
log. Approved queries execute on a queue worker with cursor streaming, results
are masked by your rules as they are written, and every step lands in an
append-only audit log that the application never edits or deletes from; the
[audit trail post](/blog/production-query-audit-trail/) covers what that record
should contain. The `WHERE` rule is explained in
[how to stop `UPDATE` and `DELETE` without `WHERE`](/blog/prevent-update-delete-without-where/).

See the [approval workflow documentation](/docs/approval-workflow/) for the
roles and the exact lifecycle, or the [SQL guards reference](/docs/sql-guards/)
for what the parser rejects. The guards differ by engine; see
[PostgreSQL](/postgresql-access-control/),
[MySQL and MariaDB](/mysql-mariadb-access-control/) and
[SQL Server](/sql-server-access-control/). For how the approval record and the
audit trail relate to audit evidence, see
[SOC 2 and database access controls](/soc-2-database-access-controls/).

## Frequently asked

### What is a SQL query approval workflow?

A process in which a developer submits a SQL statement for review rather than running it directly, a second person approves or rejects it, and the approved statement is then executed by the system on the developer's behalf. The developer never holds the database credential and never executes the query themselves.

### Who should approve production queries?

Someone who understands the schema and is not the requester — usually a DBA or a senior engineer who owns that database. The one rule worth enforcing in software rather than in policy is that nobody approves their own request.

### Does an approval workflow slow teams down?

It adds a wait, and the length of that wait is the whole design problem. When approvals arrive as a chat message with two buttons, the wait is typically minutes. When they require opening a separate tool and hunting for a queue, people route around the system, which is worse than not having it.

### What happens to rejected queries?

A rejected request stays in the audit trail with its reason, so the record shows what was asked as well as what ran. The developer revises and resubmits rather than losing the work.
