# Source: https://planetscale.com/docs/vitess/troubleshooting/planetscale-system-limits.md

# Source: https://planetscale.com/docs/vitess/scaling/planetscale-system-limits.md

# Vitess system limits

<Note>
  We can sometimes manually adjust limits on a per-database level. If you are facing issues or have questions, the best course of action is to [open a support ticket](https://planetscale.com/contact).

  Additionally, you can find some solutions to specific error codes in the [Errors documentation](/docs/vitess/troubleshooting/errors).
</Note>

## Table limits

Database schemas are limited to a total of `2048` tables, including views.

Individual tables are limited to a maximum of `1017` columns each.

## Disk limits

For [**network-attached storage**](/docs/plans/planetscale-skus#network-attached-storage) databases, the disk size will auto-scale up to a maximum of 4 TB.
For [**Metal** databases](/docs/plans/planetscale-skus#metal), the disk size is dictated by what you choose when the database is created.
Disk sizes range from 110 GB to 7.4 TB.
Which sizes are available depends on the compute instance chosen.

This space is used both for user data as well as system data required to run database operations.

If your database is near this limit, some deploy request operations may not be available as they require adequate disk space to complete.

When near this limit, we recommend either [sharding your data](/docs/vitess/sharding) or distributing tables across multiple keyspaces.
For Metal databases, you can try upgrading to a larger disk size.
Please [contact us](https://planetscale.com/contact) to discuss options.

## Connection lifetime limits

Database client connections that are held open longer than `24 hours` may be terminated unexpectedly. We recommend that long-running database connections are closed and reconnected at least once per day.

## Simultaneous transaction limits

Each database has a limit on the number of simultaneous *transactions* it can process, also known as the *transaction pool*.
If you exceed the *transaction pool* setting for your database, you may encounter this error:

```
vttablet: rpc error: code = ResourceExhausted desc = transaction pool connection limit exceeded
```

This can often be mitigated by trying one of the following solutions:

A) Reduce the amount of parallelism in the requests being sent to the database. <br />
B) Shorten lengthy transactions by reducing batch sizes or making some other application-level adjustment.

If you cannot make such changes to your application, consider choosing a larger instance type with a larger transaction pool.
The exact limit varies depending on the instance type of your database.
For details, see the [plans page](/docs/plans/planetscale-skus).

## Query limits

PlanetScale has enforced some system limits to prevent long-running queries or transactions from:

* Piling up and consuming all available resources.
* Blocking other important, short-lived queries and transactions from completing.
* Overloading the database to the point where it is not recoverable without a restart.
* Blocking planned failovers and critical upgrades.

The following table details these limits:

| Type                                         | Limit  |
| :------------------------------------------- | :----- |
| Per-query rows returned, updated, or deleted | 100k   |
| Per-query result set total size              | 64 MiB |
| Per-query autocommit timeout                 | 900s   |
| Per-transaction timeout                      | 20s    |

### Recommendations for handling query limits

These limits are enforced for the safety of your database. However, we do understand you may run into a situation where the limits are a blocker. Here are some best practices for solving common issues presented by the limits:

**What should I do if I have a query that returns more than 100,000 records?**

We recommend trying to break up large queries, e.g. through [pagination](https://planetscale.com/blog/mysql-pagination).

**What should I do if I have a query that returns more than 64 MiB of data?**

If your schema currently relies on storing large amounts of variable length data within `JSON`, `BLOB`, or `TEXT` type columns that is regularly over a few MiB in size, you will want to strongly consider storing that variable length data outside of your database, such as within an object storage solution, instead.

If large values are stored within variable length data columns, it can limit the number of rows you can return.

For example, above we described a 100K limit for result sets, but if your result set's size exceeds the 64 MiB limit then you may receive an error message like the following: `resource_exhausted: grpc: received message larger than max (<RESULT_SET_SIZE_IN_BYTES> vs. 67108864)` when retrieving much less than 100K rows.

Similarly, when generating a large `INSERT` or `UPDATE` query for these types of columns you may run into the `grpc: trying to send message larger than max (<QUERY_SIZE_IN_BYTES> vs. 67108864)` error message which would require you to reduce the query's size.

**What should I do if I have a transaction that runs longer than 20 seconds?**

For transactions that are running for longer than 20 seconds, we recommend breaking these up into multiple shorter transactions. For analytics queries that are not possible to break up, see "How should I handle analytical queries?" below.

Keep your transactions small and short-lived. For transactional workloads that are inherently long-lived, consider replacing or complementing MySQL transactions with other techniques:

* For simple workloads (e.g. a `SELECT`, followed by an HTTP request, followed by an `UPDATE`), consider using optimistic locking instead of transactions.
* For complex workloads, consider using sagas to coordinate a series of small, short-lived transactions that possibly span multiple microservices.

**What should I do if I have a select query that needs to timeout faster than 900 seconds?**

For select statements only, you can provide an inline comment to kill the query if it has not returned results within the specified time in milliseconds. `select /*vt+ QUERY_TIMEOUT_MS=2000 */ sleep(3);` Please note, you can set this value shorter than 900 seconds but not greater than the 900 seconds default.

**How should I handle analytical queries?**

We recommend using [PlanetScale Connect](https://planetscale.com/blog/extract-load-and-transform-your-data-with-planetscale-connect) (via [Airbyte](/docs/vitess/integrations/airbyte) or [Stitch](/docs/vitess/integrations/stitch)) to extract your data to any compatible destination (e.g. BigQuery, Redshift, etc.). The analytics queries should then be performed at those destinations.

### OLAP mode

While it is possible to bypass these safety limits using `OLAP` mode (`SET workload = OLAP`), we do not recommend this for the reasons listed at the beginning of this doc. In OLAP mode, you may return more than 100k rows from a single query, but the 100k row limit will still apply to updates and deletes.

When the use of OLAP queries is strictly unavoidable, we recommend:

* Where possible, sending those queries to a replica. Every PlanetScale database comes with at least two replicas. Learn how to send queries to replicas using [global replica credentials](/docs/vitess/scaling/replicas#how-to-query-replicas).
* Carefully and regularly reviewing the performance of those queries with [PlanetScale Insights](/docs/vitess/monitoring/query-insights).

<Note>
  If you choose to use OLAP mode, be prepared to handle errors that may occur if the connection to PlanetScale gets interrupted.
</Note>

## Reducing table size without `OPTIMIZE TABLE`

If you delete several rows in a table, you may wish to reclaim that storage space. The MySQL [`OPTIMIZE TABLE` statement](https://dev.mysql.com/doc/refman/en/optimize-table.html) allows you to reorganize the physical storage of table data to reduce its storage requirements.

However, `OPTIMIZE TABLE` is a locking operation, so you cannot use it unless you disable [safe migrations](/docs/vitess/schema-changes/safe-migrations) in PlanetScale, which is not recommended.

Any time you create and deploy a deploy request with safe migrations on, our schema change process uses [online DDL](/docs/vitess/schema-changes/how-online-schema-change-tools-work), and in doing so, recreates the table that you are modifying — thus reclaiming the storage space.

But there are often cases where you do not need to make a schema change for a while, but you'd like to free up the space. In those cases, we suggest you do the following:

<Steps>
  <Step>
    Create a new branch.
  </Step>

  <Step>
    Run the following command:

    ```sql  theme={null}
    ALTER TABLE <TABLE_NAME> COMMENT 'Optimize table size via DR - <YYYY-MM-DD>';
    ```

    Where `<TABLE_NAME>` is the name of your table and `<YYYY-MM-DD>` is the current date.
  </Step>

  <Step>
    Create a deploy request, and merge it into production.

    If you use this option you will likely want to [throttle the deploy request](/docs/vitess/schema-changes/throttling-deploy-requests#managing-throttler-settings-per-deploy-request) running the `ALTER TABLE`.
  </Step>
</Steps>

## Need help?

Get help from [the PlanetScale Support team](https://support.planetscale.com/), or join our [GitHub discussion board](https://github.com/planetscale/discussion/discussions) to see how others are using PlanetScale.


---

> To find navigation and other pages in this documentation, fetch the llms.txt file at: https://planetscale.com/llms.txt