Data Table Size Validation Fails After Deleting Data

Describe the problem/error/question

My data tables reached the max size (50 MB) and Get/Update operations began to fail. I see this message at the top of the page:

50 / 50MB of data tables storage used, operations may fail. Delete data to avoid errors

I’ve deleted most of the data, but the message persists, the Data Tables page continues to show the old, maxed-out data table sizes (pre-deletion), and operations continue to fail.

What is the error message (if any)?

50 / 50MB of data tables storage used, operations may fail. Delete data to avoid errors

Validation error with data table request: Data table size limit exceeded: 50MB used, limit is 50MB

Information on your n8n setup

  • n8n version: 2.1.4
  • Database (default: SQLite): Postgres
  • n8n EXECUTIONS_PROCESS setting (default: own, main): Unsure, probably default
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker
  • Operating system: Ubuntu

The size figure is the storage the database is still holding, not the live row count. Deleting rows frees logical space, but SQLite/Postgres do not hand that space back to the file on their own, and the Data Tables page reads the storage total - so a table can sit pinned at 50/50 MB long after you deleted the rows.

Two things worth trying: delete the whole data table and recreate it instead of trimming rows (that drops the underlying table and releases the space right away), and if you are self-hosted, stop n8n and run VACUUM on the database file (Postgres: VACUUM FULL on that table) so the space is actually reclaimed. The quota is per instance across all data tables, so check whether another table is still holding the bulk of it - and if you are on Cloud, that accounting can lag until their maintenance job runs, which is worth a ticket with your instance name.

Hi @Yaniv_Savir,

As @HomelabAgent accurately pointed out, this is a classic PostgreSQL MVCC (Multi-Version Concurrency Control) dead-tuple allocation behavior, rather than an n8n workflow node caching glitch.

When you execute a standard DELETE query or trim data via the UI, PostgreSQL does not physically shrink the file size on disk or return the blocks to the OS. Instead, it merely marks those row boundaries as “dead tuples” internally. Because n8n’s data table validation engine queries the total physical storage layout metric rather than performing a live active row count, your instance remains pinned at 50 / 50MB used, causing all subsequent upstream mutations to fail with a validation exit.

Here is how to reclaim the storage space immediately on your self-hosted setup:

Since you are running n8n via Docker on Ubuntu, you have two direct infrastructure options to flush the table allocation:

Option 1: The VACUUM FULL Execution (Recommended if you want to keep the empty tables)

You need to force PostgreSQL to reclaim the dead-tuple space by completely rewriting the target table file. Run this command directly inside your database container or via a terminal client connected to your Postgres instance:

VACUUM FULL execution_entity;
VACUUM FULL workflow_entity;

(Note: If you are using custom n8n data tables, replace the entity names above with your specific data table database names. Keep in mind that VACUUM FULL places an exclusive write-lock on that table momentarily, so pause active webhook intake lines for a few seconds during execution).

Option 2: Drop and Recreate (Fastest if table schema can be flushed)

If you don’t care about the historical metadata schema boundary, completely Drop or delete the data table through the n8n UI or database terminal and recreate a fresh instance. Dropping a table instantly releases the underlying physical file blocks back to the system, dropping the quota metric back to 0 MB.

Long-term Production Fix:

To prevent your self-hosted n8n database from bloating to the 50 MB threshold again under high-volume webhooks, you should configure the automatic pruning environment variables inside your compose.yaml or .env file:

EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=168 (Deletes executions older than 7 days)
EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000

I maintain an open-source hardened architecture pattern specifically tuned for managing PostgreSQL database transactions, state persistence, and webhook optimization cleanly under Docker setups.

Feel free to review the indexing and table logic here if it helps optimize your infrastructure stability:
:link: https://github.com

Let me know if running the VACUUM FULL query drops the 50MB storage warning label!

A small correction before trying the SQL above: execution_entity and workflow_entity are not the Data Tables you created. I would not run VACUUM FULL on them to fix this quota warning. PostgreSQL says FULL holds an exclusive lock for the whole rewrite, so this is not necessarily a few-second operation: PostgreSQL: Documentation: 18: VACUUM

First, back up the database and confirm the remaining row counts and sizes for the actual affected Data Tables. If rows are gone but the reported size stays unchanged, include those before/after figures, your 2.1.4 version and the failing operation in a bug report. That helps distinguish storage accounting from retained table space rather than assuming either cause.

The current n8n docs also document N8N_DATA_TABLES_MAX_SIZE_BYTES for self-hosted instances. Check support in your installed version before using that as temporary headroom; it does not explain why deleting rows failed to lower the figure. Data tables | Build | n8n Docs