Update docs based on SRE Agent findings (#50910)

## Problem

SRE Agent running against a project which is read-only due to disk being
full.

## Solution

The SRE agent struggled to find the information which is now included in
this PR.

<!--
## Preview links

If relevant, include links to changed pages for easy review access.

Copy the preview base URL from the Vercel bot comment on this PR. Use
the following table as an example template.

| Site | Live | Preview | Search for |
| -------------- |
-------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------
| ----------------------------- |
| WWW | [/blog/your-post](https://supabase.com/blog/your-post) |
[/blog/your-post](https://zone-www-dot-com-git-branch-name-supabase.vercel.app/blog/your-post)
| unique phrase from the change |
| Docs |
[/docs/guides/your-page](https://supabase.com/docs/guides/your-page) |
[/docs/guides/your-page](https://docs-git-branch-name-supabase.vercel.app/docs/guides/your-page)
| unique phrase from the change |
| Studio | [/dashboard](https://supabase.com/dashboard) |
[/dashboard](https://studio-git-branch-name-supabase.vercel.app/dashboard)
| unique phrase from the change |
| Design system | [/design-system](https://supabase.com/design-system) |
[/design-system](https://design-system-git-branch-name-supabase.vercel.app/design-system)
| unique phrase from the change |
| UI library | [/library](https://supabase.com/library) |
[/library](https://ui-library-git-branch-name-supabase.vercel.app/library)
| unique phrase from the change |
| Knowledge base |
[/kb/guides/your-page](https://supabase.com/kb/guides/your-page) |
[/kb/guides/your-page](https://kb-git-branch-name-supabase.vercel.app/kb/guides/your-page)
| unique phrase from the change |
-->

<!-- ## Additional context

Optionally add any other context or screenshots.

-->

## Review instructions

- https://supabase.com/docs/guides/api/rest/postgrest-error-codes
- https://supabase.com/docs/guides/observability/advanced-log-filtering
- https://supabase.com/docs/guides/platform/database-size

## Checklist

Check all before review:

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which references
[WORD_LIST](https://github.com/supabase/supabase/blob/master/apps/docs/WORD_LIST.md)
and the docs
[CONTRIBUTING](https://github.com/supabase/supabase/blob/master/apps/docs/CONTRIBUTING.md)
guide


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added guidance for recognizing platform-related PostgreSQL errors,
including read-only mode, disk exhaustion, connection-pool limits, and
database restarts or failovers.
* Added SQL queries for grouping PostgreSQL errors and reviewing recent
error events while filtering out selected platform-level codes.
* Clarified that read-write transaction settings apply only to the
current session, and that background writes resume automatically after
read-only mode ends.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Steven Eubank authored and GitHub committed 2026-09-29 20:55:02 -05:00
1 parent a9c594a820
commit ad0ed2cdbc
3 files changed
+73 -2

No files matched your search

@@ -67,6 +67,19 @@ Here's the text formatted as a proper markdown table:
| 42501 | if authenticated 403, else 401 | insufficient privileges |
| other | 400 | |
<Admonition type="note">
Some codes in this table are triggered by platform conditions rather than application code. Seeing them in high volume usually points to an infrastructure event rather than a bug in your queries:
- **25006** — The database has entered read-only mode due to disk quota. See [Read-only mode](/docs/guides/platform/database-size#read-only-mode) for causes and recovery steps.
- **53100** — Disk is full. Supabase emits this alongside 25006 during severe disk exhaustion.
- **53300** — Too many connections. The connection pool has reached its limit; check your [connection pool settings](/docs/guides/database/connection-management).
- **57P03** — The database cannot accept connections, typically during a restart or failover.
When you see these codes in volume, check the [Database dashboard](/dashboard/project/_/observability/database) before debugging application code.
</Admonition>
## API level errors
### Connection errors
@@ -95,6 +95,41 @@ limit 100;
Combine predicates with `and`, `or`, and `not`. Select only the fields needed for the investigation. To correlate sources, use an identifier present in both; a shared timestamp alone does not establish that events belong to the same request.
## Filter by Postgres error code [#sqlstate-filtering]
Filter `postgres_logs` by SQLSTATE to surface errors at a specific category rather than by message text. The code lives in `log_attributes['parsed.sql_state_code']`.
To see which error codes are occurring across a time window:
```sql
select
log_attributes['parsed.sql_state_code'] as sqlstate,
count() as occurrences
from logs
where source = 'postgres_logs'
and log_attributes['parsed.sql_state_code'] != ''
group by sqlstate
order by occurrences desc
limit 50;
```
During a platform-level incident (such as the database entering read-only mode), codes like `25006` (`read_only_sql_transaction`) and `53100` (`disk_full`) will dominate the results. To focus on application errors while a platform incident is active, exclude the known platform codes:
```sql
select
timestamp,
log_attributes['parsed.sql_state_code'] as sqlstate,
event_message
from logs
where source = 'postgres_logs'
and log_attributes['parsed.sql_state_code'] not in ('25006', '53100', '57P03')
and log_attributes['parsed.error_severity'] = 'ERROR'
order by timestamp desc
limit 50;
```
SQLSTATE codes starting with `25` or `53` usually indicate platform-level resource events rather than application bugs. See the [PostgREST error codes reference](/docs/guides/api/rest/postgrest-error-codes#database-level-errors) and [Database size guide](/docs/guides/platform/database-size#read-only-mode) for context.
## Query limits [#limit-and-result-row-limitations]
Use an explicit `limit` and narrow time range. The logs query surface rejects `select *` and `count(*)`; list columns and use `count()`. A result limit bounds returned rows, not the time range scanned.
@@ -124,7 +124,24 @@ To resolve it, upgrade your plan or disable your Spend Cap to lift the restricti
In some cases Supabase may put your database into read-only mode to prevent your database from exceeding the billing or disk limitations.
In read-only mode, clients will encounter errors such as `cannot execute INSERT in a read-only transaction`. Regular operation (read-write mode) is automatically re-enabled once usage is below 95% of the disk size,
In read-only mode, clients will encounter errors such as `cannot execute INSERT in a read-only transaction`. The Postgres SQLSTATE code for this error is **25006** (`read_only_sql_transaction`). During severe disk exhaustion, **SQLSTATE 53100** (`disk_full`) may also appear. Regular operation (read-write mode) is automatically re-enabled once usage is below 95% of the disk size.
While in read-only mode, all write operations are blocked — including background jobs, scheduled tasks, and internal monitoring writes. Data that those jobs write (such as disk usage snapshots) will be stale until the database returns to read-write mode.
To confirm that your database has entered read-only mode, query Postgres logs for the relevant SQLSTATE codes using the [Logs Explorer](/dashboard/project/_/logs/explorer) with the query source set to **Logs**:
```sql
select
timestamp,
log_attributes['parsed.error_severity'] as severity,
log_attributes['parsed.sql_state_code'] as sqlstate,
event_message
from logs
where source = 'postgres_logs'
and log_attributes['parsed.sql_state_code'] in ('25006', '53100', '57P03')
order by timestamp desc
limit 50;
```
### Disabling read-only mode
@@ -136,7 +153,7 @@ First, change the [transaction access mode](https://www.postgresql.org/docs/curr
set session characteristics as transaction read write;
```
This allows you to delete data from within the session. After deleting data, consider running a vacuum to reclaim as much space as possible:
This allows you to delete data from within the current session. After deleting data, consider running a vacuum to reclaim as much space as possible:
```sql
vacuum;
@@ -148,6 +165,12 @@ Once you have reclaimed space, you can run the following to disable [read-only](
set default_transaction_read_only = 'off';
```
<Admonition type="note">
`SET SESSION CHARACTERISTICS` applies only to the current session. Background jobs and scheduled tasks resume writes automatically once the platform exits read-only mode — no manual step is needed.
</Admonition>
### Disk size distribution
You can check the distribution of your disk size on your [project's Infrastructure page](/dashboard/project/_/settings/infrastructure).