# Top Postgres SQL Review Tools in 2026

> Postgres SQL review tools compared: SQLFluff for style, Squawk for migration safety, plpgsql_check and pgTAP, and where Bytebase fits as the approval layer.

Adela | 2026-07-28 | Source: https://www.bytebase.com/blog/top-postgres-sql-review-tools/

---

> **Note:** This post is maintained by Bytebase, an open-source database governance platform. We update the post periodically.

Postgres has more SQL review tooling than most engines, and less of it overlaps than you'd expect. A style linter, a migration-safety linter, and a stored-procedure static analyzer solve three different problems, and none of them substitute for the other two. Add a platform that gates the merge on a human approval, and you have four separate jobs that people keep asking one tool to do.

What are the criteria? Every pick here is:

- **Postgres-aware** - general SQL linters that treat Postgres as just another dialect are noted, but the picks below either target Postgres specifically or have real Postgres-specific rule coverage.
- **Actively maintained** - verified as of July 2026, version numbers named where they matter.
- **Adoptable on its own** - no pick requires the others to be useful.

## SQLFluff (Postgres dialect)

[SQLFluff](https://sqlfluff.com/) is a style linter, not a safety linter. It parses SQL against a chosen dialect and flags casing, indentation, and formatting violations. The Postgres dialect defaults to lowercase keywords and single-quoted string literals, which matters if your team's SQL style disagrees with that default; you configure it once in `.sqlfluff` and it applies everywhere.

It has no idea that `ADD COLUMN ... DEFAULT now()` rewrites the entire table because the default is volatile, while the same statement with a constant default does not. Style and safety are different layers, and SQLFluff only covers the first one. Pair it with something that covers the second.

**Best for:** enforcing one SQL style across a team, in CI, before it ever reaches a human reviewer.

## Squawk

[Squawk](https://squawkhq.com/) is the opposite of SQLFluff: it does not care about style, only about what a statement will do to a running database. Its 39 rules are named after the mistakes they catch. `adding-field-with-default` flags the classic one: before Postgres 11, adding a column with any default rewrote the whole table under an `ACCESS EXCLUSIVE` lock. Postgres 11 fixed that for constant defaults, but a volatile default like `now()` still rewrites, on every version. `adding-not-nullable-field` catches a different failure: setting an existing column `NOT NULL` scans the table to verify no nulls, and errors out if it finds one. Postgres 12 added a way to skip that scan if a validated `CHECK` constraint already proves the column is null-free. `disallowed-unique-constraint` and `require-concurrent-index-creation` cover the index side.

Pinning the target Postgres version is what makes those rules useful, because the correct answer genuinely differs by release. It runs in CI against migration files, not against ad-hoc queries, so it will not catch a runaway `SELECT` a developer runs by hand.

**Best for:** teams running Postgres migrations through CI who have been burned by a lock they didn't see coming. This is close to a must-have if nothing else on this list is in place yet.

## plpgsql_check

Most of the tools here look at the SQL you send. [plpgsql_check](https://github.com/okbob/plpgsql_check) looks at the stored procedures already living inside the database. It's a Postgres extension, not a CLI, and it statically analyzes PL/pgSQL functions: unused variables, missing `RETURN` paths, type mismatches between a function's declared parameters and how it's actually called, and SQL injection risk in dynamic `EXECUTE` statements.

Version 2.9.0 (May 2026) reworked the profiler, and Postgres 14 through 18 are supported. Installing it means extension privileges, so check your provider's allowlist the same way you would for PostgreSQL Anonymizer. Supabase ships it as an available extension, which is the easiest way to try it without touching your own server config.

**Best for:** teams with real logic living in stored procedures, not just tables and views. If your Postgres usage is pure SQL with no PL/pgSQL, skip this one; there's nothing for it to check.

## pgTAP

[pgTAP](https://pgtap.org/) is a testing framework, not a linter, and it's worth separating from the rest of this list for that reason. Instead of flagging a statement as risky, you write assertions (`ok()`, `is()`, `has_table()`, `throws_ok()`) and run them against the schema, the way you'd write unit tests against application code. It runs inside Postgres itself via PL/pgSQL, and outputs the TAP format that most CI test runners already understand.

Where this earns its place: verifying a migration actually produced the schema you intended, not just that it ran without an error. `has_column('users', 'email')` after a migration catches a silently-skipped step that a linter never would, because the migration didn't do anything unsafe. It just didn't do what you meant.

**Best for:** schema changes complex enough that "it applied without an error" isn't proof it's correct.

## Redgate and Flyway rule packs

Two commercial paths worth naming because teams already paying for them assume Postgres coverage is included. [Redgate SQL Prompt](https://www.red-gate.com/products/sql-prompt/) is style-and-formatting linting, comparable to SQLFluff but IDE-integrated rather than CLI-first, with no migration-safety checking layered on top. [Flyway Teams](https://www.red-gate.com/products/flyway/teams/) SQL checks bundle 74+ rules across SQLFluff plus Redgate's own rule set, and Postgres is one of the supported engines, though the rule set isn't Postgres-specific the way Squawk's is.

**Best for:** shops already on Flyway Teams or the Redgate toolchain who want one more layer without adding a new vendor.

## Bytebase

[Bytebase](https://www.bytebase.com/sql-review/) runs a different kind of rule: not "will this lock the table" but "does your organization's policy allow this change, on this environment, from this person." Its rule engine ships 100+ built-in checks (naming, anti-patterns, indexing, locking statements) that apply the same way across Postgres and 20+ other engines, and the differentiator over the tools above is where the check happens: inside the same change issue a DBA approves, not in a separate CI log the approver has to go find.

The honest trade-off: Bytebase's rule engine does not go as deep into single-engine specifics as Squawk does for lock analysis, or plpgsql_check does for function internals. Teams running strict Postgres migrations often layer Squawk in CI *and* Bytebase for the approval gate, rather than picking one; both wire into the same pull request when Bytebase runs as a [GitHub check](/blog/integrate-sql-review-into-github/) rather than through the GUI.

**Best for:** teams that already have a linter catching bad SQL and are missing the second half: who approved letting it through, and on what policy.

## Comparison

| Tool | Layer | Scope | Version (2026) | License |
| --- | --- | --- | --- | --- |
| SQLFluff | Style | SQL text | Monthly releases | Open source (MIT) |
| Squawk | Migration safety | Migration files | 2.x, 39 rules | Open source (Apache-2.0 / MIT) |
| plpgsql_check | Function static analysis | PL/pgSQL functions | 2.9.0 (May 2026) | Open source (MIT) |
| pgTAP | Testing | Schema assertions | 1.3.5 | Open source (PostgreSQL License) |
| Redgate SQL Prompt | Style | SQL text | Commercial release | Commercial |
| Flyway Teams SQL checks | Style + limited safety | Migration files | 74+ rules | Commercial |
| Bytebase | Policy + approval | Change workflow | 100+ rules, 20+ engines | Free (Community) / paid tiers |

Read the table by what's missing from your stack, not by which row has the most features. A team running SQLFluff alone has style consistency and zero migration-safety coverage. A team running Squawk alone catches locks but ships whatever style each developer prefers. None of these tools compete with each other; they stack.

## Picking one

Start with Squawk if you run Postgres migrations through CI and nothing here is in place yet. It catches the failure mode that actually pages someone at 2am, and it catches the version-dependent ones a senior reviewer misses because they learned the rule on a different release. SQLFluff is the next add, purely because it's nearly free to turn on and ends the style arguments in code review.

plpgsql_check and pgTAP are narrower bets: reach for the first only if real logic lives in stored procedures, and the second when a migration's correctness matters more than whether it merely avoided an error. Bytebase and the Redgate/Flyway rule packs solve a different problem than any of the above: they're not asking whether the SQL is safe, they're asking whether the right person signed off before it ran. Once you're past a single-person team, that question shows up regardless of how good your linting already is.

For the semantic rules a review tool should actually enforce, [require a primary key](/blog/sql-review-rule-explained-require-primary-key/) and [prohibit cascading deletes](/blog/sql-review-rule-explained-prohibit-cascade/) are two concrete examples worth reading past the tool comparison. For the naming and design conventions to pair with whichever linter you pick, see the [Postgres SQL review and style guide](/blog/postgres-sql-review-guide/). And for the three-layer framework this list assumes (linting, semantic rules, policy), [SQL review: from linting to governance](/blog/sql-review-tool-for-devs/) is the place to start.

## Related reading

- [SQL Review: From Linting to Governance](https://www.bytebase.com/blog/sql-review-tool-for-devs/)
- [PostgreSQL SQL Review and Style Guide](https://www.bytebase.com/blog/postgres-sql-review-guide/)
- [Is SQL Review Necessary? Real Talk From Developers](https://www.bytebase.com/blog/is-sql-review-necessary/)
- [How to Integrate Automatic SQL Review into GitHub](https://www.bytebase.com/blog/integrate-sql-review-into-github/)