Rules

Below the list of rules supported by the Postgres Language Server, divided by group. Here's a legend of the emojis:

  • The icon ✅ indicates that the rule is part of the recommended rules.

Safety

Rules that detect potential safety issues in your code.

Rule name Description Properties
addSerialColumn Adding a column with a SERIAL type or GENERATED ALWAYS AS ... STORED causes a full table rewrite.
addingFieldWithDefault Adding a column with a DEFAULT value may lead to a table rewrite while holding an ACCESS EXCLUSIVE lock.
addingForeignKeyConstraint Adding a foreign key constraint requires a table scan and a SHARE ROW EXCLUSIVE lock on both tables, which blocks writes.
addingNotNullField Setting a column NOT NULL blocks reads while the table is scanned.
addingPrimaryKeyConstraint Adding a primary key constraint results in locks and table rewrites.
addingRequiredField Adding a new column that is NOT NULL and has no default value to an existing table effectively makes it required.
avoidAddingExclusionConstraint Adding an exclusion constraint acquires an ACCESS EXCLUSIVE lock.
avoidAlterEnumAddValue ALTER TYPE ... ADD VALUE cannot run inside a transaction block in older Postgres versions.
avoidAttachingPartition Attaching a partition acquires an ACCESS EXCLUSIVE lock on the parent table.
avoidCreateTrigger Creating a trigger acquires a SHARE ROW EXCLUSIVE lock on the table.
avoidEnableDisableTrigger Enabling or disabling a trigger acquires a SHARE ROW EXCLUSIVE lock.
avoidWideLockWindow Acquiring ACCESS EXCLUSIVE locks on multiple tables widens the lock window.
banCharField Using CHAR(n) or CHARACTER(n) types is discouraged.
banConcurrentIndexCreationInTransaction Concurrent index creation is not allowed within a transaction.
banDeleteWithoutWhere A DELETE statement without a WHERE clause will remove all rows from the table.
banDropColumn Dropping a column may break existing clients.
banDropDatabase Dropping a database may break existing clients (and everything else, really).
banDropNotNull Dropping a NOT NULL constraint may break existing clients.
banDropSchema Dropping a schema will remove all objects within it and may break existing clients.
banDropTable Dropping a table may break existing clients.
banDropTrigger Dropping a trigger acquires an ACCESS EXCLUSIVE lock on the table.
banTruncate Truncating a table removes all rows and can cause data loss in production.
banTruncateCascade Using TRUNCATE's CASCADE option will truncate any tables that are also foreign-keyed to the specified tables.
banUpdateWithoutWhere An UPDATE statement without a WHERE clause will modify all rows in the table.
banVacuumFull VACUUM FULL rewrites the entire table and acquires an ACCESS EXCLUSIVE lock.
changingColumnType Changing a column type may require a table rewrite and break existing clients.
concurrentRefreshMatviewLock REFRESH MATERIALIZED VIEW CONCURRENTLY still acquires an EXCLUSIVE lock.
constraintMissingNotValid Adding constraints without NOT VALID blocks all reads and writes.
creatingEnum Creating enum types is not recommended for new applications.
disallowUniqueConstraint Disallow adding a UNIQUE constraint without using an existing index.
lockTimeoutWarning Taking a dangerous lock without setting a lock timeout can cause indefinite blocking.
multipleAlterTable Multiple ALTER TABLE statements on the same table should be combined into a single statement.
preferBigInt Prefer BIGINT over smaller integer types.
preferBigintOverInt Prefer BIGINT over INT/INTEGER types.
preferBigintOverSmallint Prefer BIGINT over SMALLINT types.
preferIdentity Prefer using IDENTITY columns over serial columns.
preferJsonb Prefer JSONB over JSON types.
preferRobustStmts Prefer statements with guards for robustness in migrations.
preferTextField Prefer using TEXT over VARCHAR(n) types.
preferTimestamptz Prefer TIMESTAMPTZ over TIMESTAMP types.
renamingColumn Renaming columns may break existing queries and application code.
renamingTable Renaming tables may break existing queries and application code.
requireConcurrentDetachPartition Detaching a partition without CONCURRENTLY acquires an ACCESS EXCLUSIVE lock.
requireConcurrentIndexCreation Creating indexes non-concurrently can lock the table for writes.
requireConcurrentIndexDeletion Dropping indexes non-concurrently can lock the table for reads.
requireConcurrentRefreshMatview REFRESH MATERIALIZED VIEW without CONCURRENTLY acquires an ACCESS EXCLUSIVE lock.
requireConcurrentReindex REINDEX without CONCURRENTLY acquires an ACCESS EXCLUSIVE lock on the table.
requireIdleInTransactionTimeout Dangerous lock statements should be preceded by SET idle_in_transaction_session_timeout.
requireSeparateConstraintValidation Validating a constraint in the same transaction it was added as NOT VALID defeats the purpose.
requireStatementTimeout Dangerous lock statements should be preceded by SET statement_timeout.
runningStatementWhileHoldingAccessExclusive Running additional statements while holding an ACCESS EXCLUSIVE lock blocks all table access.
transactionNesting Detects problematic transaction nesting that could lead to unexpected behavior.