Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →In PostgreSQL, lock_timeout limits how long a statement can wait to acquire a lock. Set it in the migration’s own session or transaction, and a schema change that cannot get its lock fails quickly instead of queuing behind live traffic indefinitely. That is the incident it prevents. It does not make a migration safe, bound the migration’s total runtime, or make a breaking schema change compatible with the application code already running. No reviewed source measures how often teams set this parameter, so treat the headline as a practical guardrail rather than a statistic.
Why a waiting migration hurts production
Most schema changes that look trivial, such as adding a nullable column or renaming a column, still need an exclusive lock on the table. That lock cannot be granted while other transactions hold a conflicting lock on the table, such as a long-running report or a transaction left open by an application. The migration waits. While it waits, it sits in the lock queue, and every later query that needs the same table queues behind it. A migration that was supposed to take milliseconds can therefore stall the whole table for as long as the blocking transaction runs.
As an Amazon Associate I earn from qualifying purchases.
A lock timeout breaks that chain. If the migration gives up after a bounded wait, the queue drains, and the application keeps working. The migration is the thing that fails, which is the outcome you want to see during a deployment.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
What lock_timeout measures
According to the PostgreSQL documentation (PostgreSQL Global Development Group, “Client Connection Defaults”), lock_timeout is the maximum time a statement waits to acquire any single lock. The clock applies separately to each lock acquisition. If a wait exceeds the setting, the statement is aborted. Its default is 0, which disables the limit, so PostgreSQL will wait for a lock indefinitely unless you configure otherwise.
#1 Best Overall
The setting does not measure how long the statement runs once it has its locks. A migration that acquires its lock within the limit and then spends twenty minutes rewriting rows is not stopped by lock_timeout.
lock_timeout versus statement_timeout
The two settings are often confused because both abort statements. They bound different things.
| Aspect | lock_timeout | statement_timeout |
|---|---|---|
| What is timed | Time spent waiting to acquire each lock | Total execution time of a statement |
| Clock behavior | Separate for each lock acquisition | One clock for the whole statement |
| Protects against | Migrations queued behind lock holders | Long-running statements of any kind |
| Default in PostgreSQL documentation | 0 (disabled) |
0 (disabled) |
| Interaction | If set to a value equal to or greater than a nonzero statement_timeout, it has no effect, because the statement timeout fires first |
Fires first when set at or below lock_timeout |
For migrations, the two are complementary. lock_timeout covers the queueing risk. statement_timeout covers the risk that a single statement runs far longer than planned. Setting only one leaves the other failure mode open.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchRank #2
Setting it for one migration
Scope the value to the migration. PostgreSQL’s documentation advises against placing lock_timeout in postgresql.conf, stating that “Setting lock_timeout in postgresql.conf is not recommended because it would affect all sessions.” A global value changes behavior for every application connection, not just the migration.
- Start the migration in its own session or transaction, separate from application connections.
- Set the timeout before the first statement that takes a lock on the affected table. For a session-wide setting, run
SET lock_timeout = '5s';. The value is illustrative, not a recommendation. - Run the lock-taking statements. If you want the setting to disappear automatically at the end of the transaction, use
SET LOCALinside an explicit transaction, as shown below.
BEGIN;
SET LOCAL lock_timeout = '5s';
ALTER TABLE orders ADD COLUMN archived_at timestamptz;
COMMIT;
With SET LOCAL, the value lasts only until the transaction ends, so it cannot leak into later statements in the same connection. A plain SET persists for the rest of the session, which is acceptable only when the session is dedicated to the migration.
Choosing a value
No single duration is correct. The official documentation defines the setting but does not prescribe one. The right value depends on two tradeoffs you have to make for your own service:
Rank #3
- Too short: the migration fails under normal traffic, even when it would have succeeded a few seconds later. You then retry more often, and each retry is another deployment step.
- Too long: while the migration waits, queries behind it wait too, so the value sets how long users can be affected by a blocked migration.
Supabase’s migration guidance acknowledges lock-timeout errors and suggests considering an increase in lock_timeout when they occur. The implication is that the value is tuned against observed behavior, not chosen once and forgotten.
What happens when the timeout fires
When the wait exceeds the limit, PostgreSQL reports a lock-timeout error and aborts the statement. Inside an explicit transaction, the error also aborts the transaction, so you must issue ROLLBACK before running anything else on that connection. Treat the result as a failed migration rather than a transient warning.
- Confirm the error is a lock timeout and that the migration did not partially apply. Check the schema for the change you intended.
- Identify the sessions holding the conflicting lock. A starting point is
SELECT pid, state, query_start, left(query, 80) FROM pg_stat_activity WHERE state <> 'idle' ORDER BY query_start;. Look for long-running transactions, especially those inidle in transactionstate. - Decide whether to wait for the blocking work to finish, retry in a lower-traffic window, or adjust the timeout. Retrying with the same value is not a fix if the same transaction keeps holding the lock.
What the setting does not protect against
- Total migration runtime. That is the job of
statement_timeout, and only for individual statements. - Incompatible changes. A migration can acquire its lock and still break running application code if it renames or drops something the old version uses.
- Destructive mistakes. A timeout does not review the SQL. Dropping the wrong column succeeds if the lock is granted.
- Rollback. The setting determines whether a statement waits, not whether its effects can be reversed.
Make breaking changes in stages
A lock timeout reduces the risk of waiting. It does not remove the need to change schemas in a way the running application can tolerate. Netlify’s migration guidance describes an expand, migrate, and contract sequence, with removal of the old structure deferred until application code has switched over. Its wording: “Still, as a good practice, we recommend that you always write backwards-compatible migrations.” (Netlify, “Migrations,” last updated April 28, 2026.)
Expand
Add the new column, table, or index without removing anything. Old application versions keep working because nothing they read has changed.
Migrate
Deploy application code that writes to the new structure and reads from it, and backfill existing rows as needed. Both old and new versions can run during the transition.
Recommended Free Tools
Contract
Once no running code depends on the old structure, remove it. Netlify notes that renaming or dropping a column can fail during the transition between old and new application versions, which is why removal waits until the last step.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Deployment tooling changes what you can review
Where the migration runs also affects how you can check it. Microsoft’s guidance for applying EF Core migrations recommends inspecting generated migrations and testing them before production, because a migration may drop a column unintentionally or fail for other reasons. The table compares the approaches the EF Core guidance describes. It covers EF Core, a framework, not PostgreSQL lock behavior, so the lock setting above still applies whichever tool you use.
| Approach | SQL reviewable before execution | Migration coordination | Permissions |
|---|---|---|---|
| Reviewed SQL scripts | Yes; the script can be reviewed and adjusted before it runs | Not stated in the EF Core guidance | Covered by the guidance; specifics not stated here |
| Bundles | Not exposed for inspection in the same way as scripts | EF Core migration locking is available in EF Core 9 and later, with limitations described in the guidance | Covered by the guidance; specifics not stated here |
| Command-line or runtime migration | Not stated in the EF Core guidance | Not stated in the EF Core guidance | Covered by the guidance; specifics not stated here |
Whatever tool generates the change, the reviewed SQL is what reaches the database, so review it with the lock timeout and the expand, migrate, and contract sequence in mind.
Sources cited: PostgreSQL Global Development Group, “Client Connection Defaults,” current PostgreSQL documentation; Supabase, “Database Migrations”; Microsoft Learn, “Applying Migrations – EF Core”; Netlify, “Migrations,” last updated April 28, 2026.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




