{
  "id": 15863406,
  "title": "Why Your Postgres Table Keeps Growing Even Though You're Deleting Rows",
  "url": "https://urgent.news/2026/10/21/why-your-postgres-table-keeps-growing-even-though-youre-deleting-rows",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-21T08:35:20.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/mohhddhassan/why-your-postgres-table-keeps-growing-even-though-youre-deleting-rows-53lh"
  },
  "original_language": "en",
  "account": "A database table can grow in size even after rows have been deleted, due to a feature called Multi-Version Concurrency Control (MVCC) in PostgreSQL. When a row is updated or deleted, PostgreSQL keeps the old version of the row around, known as a dead tuple. These dead tuples take up space until something cleans them up, which is the job of the VACUUM command. However, VACUUM only marks the space as reusable, it doesn't shrink the file on disk unless the table is completely empty. This can lead to unexpected growth in table size. To reclaim disk space, you can use VACUUM FULL, which rewrites the entire table into a new file and locks the table for the duration, or use pg_repack for a less intrusive approach. Long-running transactions can also prevent VACUUM from removing dead tuples, causing them to pile up and consume more space.",
  "summary": "A while back I noticed something odd. A table with a modest number of rows was taking far more disk space than it should. SELECT count(*) said one thing, pg_relation_size said another. I had deleted and updated plenty of rows, so where was the space going? The answer is MVCC , and once you see it, a lot of Postgres behavior starts to make sense. Let's reproduce it locally and watch it happen. The…",
  "key_points": [
    "PostgreSQL uses MVCC, keeping old row versions called dead tuples",
    "VACUUM marks space reusable, doesn't shrink file on disk",
    "VACUUM FULL rewrites table, locks it, or use pgrepack"
  ],
  "editors_take": "PostgreSQL's reliance on keeping old row versions for concurrency control forces administrators to choose between intensive table rewrites or managing long-running transactions to prevent permanent disk bloat.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}