How to fix ERROR: cannot execute INSERT/UPDATE/DELETE in a read-only transaction in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated Dec 29, 2025ยท 377 views

PostgreSQL error 25006 occurs when your session attempts to write to the database while in read-only mode. Read-only mode can be enabled at the database, session, or transaction level, preventing any INSERT, UPDATE, DELETE, or DDL operations. Disable read-only mode or connect to the primary server to resolve this.

Quick fix

Fixes 25006

SHOW default_transaction_read_only;
  1. Check if your database is in read-only mode
  2. Disable read-only mode at the database level
  3. Verify the setting changed
  4. Check if you're connected to a replica/standby
postgresql โ€” error
SHOW default_transaction_read_only;
ERROR: cannot execute INSERT/UPDATE/DELETE in a read-only transaction

What this error means

Error 25006 indicates that PostgreSQL is enforcing read-only mode to protect data integrity. When a transaction is read-only, the database rejects any attempt to modify data or schema. This happens because either the database-wide setting default_transaction_read_only is enabled, your session has read-only mode set, or you're connected to a read-only replica/standby instance. Read-only mode is commonly used for hot standby replicas, disaster recovery scenarios, or to protect databases during maintenance. The error prevents unintended data modifications in protected environments.

Typical symptoms

  • All INSERT, UPDATE, DELETE, or CREATE commands fail with this error
  • Only SELECT queries work successfully
  • Error appears immediately when attempting write operations
  • Application cannot perform any database modifications
  • CI/CD pipelines fail when trying to apply migrations or seed data
  • ORM operations like save() or update() produce this error

Common causes

  1. The database-level default_transaction_read_only parameter is set to ON for your database
  2. The session-level default_transaction_read_only is enabled for your current connection
  3. You are connected to a PostgreSQL standby/replica server in recovery mode instead of the primary
  4. The database is undergoing maintenance and has been temporarily set to read-only
  5. Your user role lacks write permissions to the database
  6. You're using a managed PostgreSQL service (Heroku, Railway, AWS RDS) during maintenance windows

How to fix "ERROR: cannot execute INSERT/UPDATE/DELETE in a read-only transaction"

1Check if your database is in read-only mode

Connect to PostgreSQL as a superuser and run:

sql
SHOW default_transaction_read_only;

If it returns "on", your database is in read-only mode. You can also check session-level settings:

sql
SELECT * FROM pg_database WHERE datname = current_database();
2Disable read-only mode at the database level

If the setting is ON, disable it for your database:

sql
ALTER DATABASE your_database SET default_transaction_read_only = off;

Replace your_database with your actual database name. This change takes effect for new connections. For immediate effect in your current session, also run:

sql
SET default_transaction_read_only = off;
3Verify the setting changed

Disconnect and reconnect to verify the change took effect:

sql
SHOW default_transaction_read_only;

It should now return "off". Try your write operation again.

4Check if you're connected to a replica/standby

If you're using PostgreSQL replication, verify you're connecting to the primary (read-write) server, not a standby:

sql
SELECT pg_is_in_recovery();

If this returns true, you're on a standby. Update your connection string to point to the primary server instead.

5Override read-only mode for a single session (temporary fix)

If you need to execute writes immediately and can't change the database setting, you can override it for your current session:

sql
SET default_transaction_read_only = off;

This affects only your current connection and will reset when you disconnect. For ORMs, check if there's a way to configure this at connection initialization.

6For managed services, check maintenance status

If using Heroku, Railway, AWS RDS, or similar services:

1. Log into your service dashboard
2. Check if your database is undergoing maintenance
3. Wait for maintenance to complete (usually 5-30 minutes)
4. Try your operation again

Upgrading to a production/standard tier usually eliminates these temporary read-only windows.

Advanced notes

Read-only mode is legitimate for standby replicas in replication setups. If you have a multi-node PostgreSQL cluster, never attempt to write to standby servers. Instead, use cascade replication or connection poolers like pgBouncer to automatically route writes to the primary.

For applications, implement connection retry logic with exponential backoff to handle temporary read-only states during maintenance. Some frameworks (e.g., Rails, Django) have built-in support for this.

You can also create deferrable read-only transactions that wait for a safe point to execute:

sql
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY DEFERRABLE;
-- Your SELECT queries here
COMMIT;

For PostgreSQL 13+, you can force terminate other connections when dropping a database:

sql
DROP DATABASE database_name WITH (FORCE);

Frequently asked questions

What does "25006" mean?
Error 25006 indicates that PostgreSQL is enforcing read-only mode to protect data integrity. When a transaction is read-only, the database rejects any attempt to modify data or schema. This happens because either the database-wide setting default_transaction_read_only is enabled, your session has read-only mode set, or you're connected to a read-only replica/standby instance.
How do I fix "25006"?
PostgreSQL error 25006 occurs when your session attempts to write to the database while in read-only mode. Read-only mode can be enabled at the database, session, or transaction level, preventing any INSERT, UPDATE, DELETE, or DDL operations. Disable read-only mode or connect to the primary server to resolve this.
What causes "25006"?
The database-level default_transaction_read_only parameter is set to ON for your database The session-level default_transaction_read_only is enabled for your current connection You are connected to a PostgreSQL standby/replica server in recovery mode instead of the primary
Is the "25006" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading