# Understanding Database and Disk Size

Understanding how database size applies to your subscription.

Disk metrics refer to the storage usage reported by Postgres. These metrics are updated daily. As you read through this document, we will refer to "database size" and "disk size":

- _Database size_: Displays the actual size of the data within your Postgres database. This can be found on the [Database Reports page](/dashboard/project/_/observability/database).

- _Disk size_: Shows the overall disk space usage, which includes both the database size and additional files required for Postgres to function like the Write Ahead Log (WAL) and other system log files. You can view this on the [Database Settings page](/dashboard/project/_/database/settings).

## Database size

This SQL query will show the size of all databases in your Postgres cluster:

```sql
select
  pg_size_pretty(sum(pg_database_size(pg_database.datname)))
from pg_database;
```

This value is reported in the [database report page](/dashboard/project/_/observability/database).

Database size is consumed primarily by your data, indexes, and materialized views. You can reduce your database size by removing any of these and running a Vacuum operation.

Depending on your billing plan, your database can go into read-only mode which can prevent you inserting and deleting data. There are instructions for managing read-only mode in the [Disk Management](#disk-management) section.

### Disk space usage

Your database size is part of the disk usage for your Supabase project, there are many components to Postgres that consume additional disk space. One of the primary components, is the [Write Ahead Log (WAL)](https://www.postgresql.org/docs/current/wal-intro.html). Postgres will store database changes in log files that are cleared away after they are applied to the database. These same files are also used by [Read Replicas](/docs/guides/platform/read-replicas) or other replication methods.

If you would like to determine the size of the WAL files stored on disk, Postgres provides `pg_ls_waldir` as a helper function; the following query can be run:

```sql
select pg_size_pretty(sum(size)) as wal_size from pg_ls_waldir();
```

### Vacuum operations

Postgres does not immediately reclaim the physical space used by dead tuples (i.e., deleted rows) in the DB. They are marked as "removed" until a [vacuum operation](https://www.postgresql.org/docs/current/routine-vacuuming.html) is executed. As a result, deleting data from your database may not immediately reduce the reported disk usage. You can use the [Supabase CLI](/docs/guides/cli/getting-started) `inspect db bloat` command to view all dead tuples in your database. Alternatively, you can run the [query](https://github.com/supabase/cli/blob/c9cce58025fded16b4c332747f819a44f45c3b83/internal/inspect/bloat/bloat.go#L17) found in the CLI's GitHub repo in the [SQL Editor](/dashboard/project/_/sql/)

```bash
# Login to the CLI
npx supabase login

# Initialize a local supabase directory
npx supabase init

# Link a project
npx supabase link

# Detect bloat
npx supabase inspect db bloat --linked
```

If you find a table you would like to immediately clean, you can run the following in the [SQL Editor](/dashboard/project/_/sql/new):

```sql
vacuum full <table name>;
```

Vacuum operations can temporarily increase resource utilization, which may adversely impact the observed performance of your project until the maintenance is completed. The [vacuum full](https://www.postgresql.org/docs/current/sql-vacuum.html) command will lock the table until the operation concludes.

Supabase projects have automatic vacuuming enabled, which ensures that these operations are performed regularly to keep the database healthy and performant.

It is possible to [fine-tune](https://www.percona.com/blog/2018/08/10/tuning-autovacuum-in-postgresql-and-autovacuum-internals/) the [autovacuum parameters](https://www.enterprisedb.com/blog/postgresql-vacuum-and-analyze-best-practice-tips), or [manually initiate](https://www.postgresql.org/docs/current/sql-vacuum.html) vacuum operations.
Running a manual vacuum after deleting large amounts of data from your DB could help reduce the database size reported by Postgres.

### Preoccupied space

New Supabase projects have a database size of ~40-60mb. This space includes pre-installed extensions, schemas, and default Postgres data. Additional database size is used when installing extensions, even if those extensions are inactive.

## Disk size

Supabase uses network-attached storage to balance performance with scalability. The disk scaling behavior depends on your billing plan.

### Paid plan behavior

Projects on the Pro Plan and higher have auto-scaling disks.

Disk size expands automatically when the database reaches 90% of the allocated disk size. The disk is expanded to be 50% larger (for example, 8 GB -> 12 GB).

Auto-scaling is limited to four modifications within a rolling 24-hour window. While a new modification can be initiated immediately after the previous one completes, reaching the quota of four resizes within the current rolling 24-hour window will prevent further scaling until the window allows it. If you reach 95% disk utilization and have exhausted your modification quota, your project will enter read-only mode.

The automatic resize operation will add an additional 50% capped to a maximum of 200 GB. If 50% of your current usage is more than 200 GB then only 200 GB will be added to your disk (for example a size of 1500 GB will resize to 1700 GB).

Disk size can also be manually expanded on the [Database Settings page](/dashboard/project/_/database/settings). The maximum disk size for the Pro/Team Plan is 60 TB. If you need more than this, [contact us](https://forms.supabase.com/enterprise) to learn more about the Enterprise Plan.

You may want to import a lot of data into your database which requires multiple disk expansions. for example, uploading more than 1.5x the current size of your database storage will put your database into [read-only mode](#read-only-mode). If so, it is highly recommended you increase the disk size manually on the [Database Settings page](/dashboard/project/_/database/settings).

Due to restrictions on the underlying cloud provider, disk modifications are limited to four operations within a rolling 24-hour window. While a new modification can be initiated as soon as the previous one completes, you will be unable to make further adjustments if you reach this rolling 24-hour limit until the rolling 24-hour window permits it.

### Free Plan behavior

Free Plan projects enter [read-only](#read-only-mode) mode when your **database size** exceeds 500 MB. Note that this is the _database size_ limit (the size of your actual Postgres data), not the _disk size_. Free Plan projects include 1 GB of disk space, but read-only mode is triggered by the 500 MB database size quota. Once in read-only mode, you have these options:

- [Upgrade to the Pro Plan](/dashboard/org/_/billing) to increase the database size quota. [Disable the Spend Cap](https://app.supabase.com/org/_/billing?panel=costControl) if you want your Pro instance to auto-scale beyond the 8 GB disk size limit.
- [Disable read-only mode](#disabling-read-only-mode) and reduce your database size.

### Read-only mode

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,

### Disabling read-only mode

You manually override read-only mode to reduce disk size. To do this, run the following in the [SQL Editor](/dashboard/project/_/sql):

First, change the [transaction access mode](https://www.postgresql.org/docs/current/sql-set-transaction.html):

```sql
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:

```sql
vacuum;
```

Once you have reclaimed space, you can run the following to disable [read-only](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-READ-ONLY) mode:

```sql
set default_transaction_read_only = 'off';
```

### Disk size distribution

You can check the distribution of your disk size on your [project's compute and disk page](/dashboard/project/_/settings/compute-and-disk).

![Disk Size Distribution](/docs/img/guides/platform/database-size/disk-size-distribution.png)

Your disk size usage falls in three categories:

- **Database** - Disk usage by the database. This includes the actual data, indexes, materialized views, ...
- **WAL** - Disk usage by the write-ahead log. The usage depends on your WAL settings and the amount of data being written to the database.
- **System** - Disk usage reserved by the system to ensure the database can operate smoothly. Users cannot modify this and it should only take very little space.

### Reducing disk size

Disks don't automatically downsize during normal operation. Once you have [reduced your database size](/docs/guides/platform/database-size#database-size), they _will_ automatically "right-size" during a [project upgrade](/docs/guides/platform/upgrading). The final disk size after the upgrade is 1.2x the size of the database with a minimum of 8 GB. For example, if your database size is 100GB, and you have a 200GB disk, the size after a project upgrade will be 120 GB.

In case you have a large WAL directory, you may [modify WAL settings](/docs/guides/database/custom-postgres-config) such as `max_wal_size`. Use at your own risk as changing these settings can have side effects. To query your current WAL size, use `SELECT SUM(size) FROM pg_ls_waldir()`.

In the event that your project is already on the latest version of Postgres and cannot be upgraded, a new version of Postgres will be released approximately every week which you can then upgrade to once it becomes available.