Skip to main content

Top Postgres SQL Review Tools in 2026

Adela · Sep 2, 2026

Update history

  1. Correct the Bytebase section: state its actual Postgres rule coverage instead of understating it against named competitors, restate the rule count as 50+ Postgres-specific (the site-wide total across all engines is 100+), and note rule levels attach to a project as well as an environment.
  2. Initial version.

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 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 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 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 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 is style-and-formatting linting, comparable to SQLFluff but IDE-integrated rather than CLI-first, with no migration-safety checking layered on top. Flyway SQL checks cover Postgres too, though the rule set isn't Postgres-specific the way Squawk's is. The edition split is worth getting right before you plan around it: Redgate's product pages currently list Community and Enterprise only, but its licensing docs (last updated May 2026) still name Flyway Teams as a licensed tier, so treat the lineup as unsettled. What's confirmed either way: Community wires in a SQLFluff install you manage yourself, and Enterprise bundles that setup, adds Redgate's own additional rules, and can gate CI on a failure.

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

Bytebase

Bytebase is where most teams end up putting the review itself, because one rule engine covers the ground the tools above split between them, and the result is attached to an approval rather than printed to a log.

For Postgres it ships 50+ rules, and several land on exactly the lock-analysis territory this list has been treating as Squawk's alone: the same rewrite-and-scan checks on ADD COLUMN ... DEFAULT and SET NOT NULL, the same CONCURRENTLY requirement on creating and dropping indexes, and the same NOT VALID-first pattern for constraints covered above. Add cascading-delete, migration-compatibility, and non-transactional-statement checks this article hasn't mentioned, and the overlap with a CI-only migration linter is real. What it isn't is version-pinned the way Squawk is: Bytebase's ADD COLUMN ... DEFAULT rule bans any default, constant or volatile, on every Postgres release, where Squawk's equivalent already knows a constant default stopped rewriting the table as of Postgres 11.

Rule levels attach to an environment or a project, with the project-level policy taking priority — the same rule can warn in dev and block in prod, or override the environment default entirely for one sensitive service. 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. It also runs as a GitHub check if you'd rather keep the gate in the pull request.

The honest trade-off is narrower than "use something else for the real review": Bytebase has no equivalent to plpgsql_check's function-body static analysis — nothing here inspects a PL/pgSQL function's internals for unused variables, missing RETURN paths, or SQL injection in a dynamic EXECUTE. If real logic lives in stored procedures, that gap is worth covering separately.

Best for: teams that want one rule engine across Postgres and their other engines, with the review and the approval in the same place.

Comparison

ToolLayerScopeVersion (2026)License
SQLFluffStyleSQL textRegular releasesOpen source (MIT)
SquawkMigration safetyMigration files2.x, 39 rulesOpen source (Apache-2.0 / MIT)
plpgsql_checkFunction static analysisPL/pgSQL functions2.9.0 (May 2026)Open source (MIT)
pgTAPTestingSchema assertions1.3.5Open source (PostgreSQL License)
Redgate SQL PromptStyleSQL textCommercial releaseCommercial
Flyway SQL checksStyle + limited safetyMigration filesCommunity: self-managed SQLFluff; Enterprise: bundled + CI-gatedFree (Community) / Commercial (Enterprise)
BytebaseLint + policy + approvalChange workflow50+ rules (Postgres)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. The Redgate/Flyway rule packs are a style-and-safety layer for shops already paying for that toolchain, with no approval gate of their own. Bytebase covers similar lock-analysis ground to Squawk, plus naming and schema-design rules, and adds what none of the above do: who signed off before the change 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 and prohibit cascading deletes 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. And for the three-layer framework this list assumes (linting, semantic rules, policy), SQL review: from linting to governance is the place to start.

Back to blog

Explore the standard for database governance