<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum" -->

---
title: All Your GUCs in a Row: min_parallel_index_scan_size and...
description: A deep dive into two PostgreSQL planner GUCs, min_parallel_table_scan_size (default 8MB) and min_parallel_index_scan_size (default 512kB), explaining how they...
canonical: https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: All Your GUCs in a Row: min_parallel_index_scan_size and min_parallel_table_scan_size | daily.dev
og:description: A deep dive into two PostgreSQL planner GUCs, min_parallel_table_scan_size (default 8MB) and min_parallel_index_scan_size (default 512kB), explaining how they...
og:url: https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum
og:image: https://api.daily.dev/og/posts/KzuFfQUUm.png
og:image:alt: All Your GUCs in a Row: min_parallel_index_scan_size and min_parallel_table_scan_size
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# All Your GUCs in a Row: min_parallel_index_scan_size and min_parallel_table_scan_size

**[Planet PostgreSQL](https://daily.dev/sources/planet-postgresql)** · 7 min read · 0 upvotes · 0 comments

## Summary

A deep dive into two PostgreSQL planner GUCs, min_parallel_table_scan_size (default 8MB) and min_parallel_index_scan_size (default 512kB), explaining how they gate eligibility for parallel scans and also set the starting rung of the tripling ladder that determines how many workers the planner requests. Includes benchmarked tables showing how worker counts change across settings, how setting either to 0 (common in test suites) can backfire in production by handing excessive workers to small tables, how CREATE INDEX and VACUUM use these parameters differently than the planner, and new PostgreSQL 19 behavior for TID range scans and parallel autovacuum. Recommends leaving both at defaults and using parallel_setup_cost or max_parallel_workers_per_gather instead for tuning.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://postgr.es/p/9wW>

## Questions this post answers

### What does min_parallel_table_scan_size actually control in PostgreSQL's query planner?

It sets the minimum table size, 8MB by default, below which a scan is not even considered for a parallel plan, but it also serves as the starting point of the tripling ladder the planner climbs to decide worker counts: one worker at that size, another each time the estimated table size triples, capped by max_parallel_workers_per_gather. Lowering it stretches the ladder and can hand more workers to small tables.

_Anyone tuning parallel query behavior can keep notes like this handy by following PostgreSQL deep dives on daily.dev._

### Why does setting min_parallel_table_scan_size to 0 in PostgreSQL cause too many parallel workers on small tables?

Setting it to 0 does not remove the minimum entirely; the planner floors the starting point at one block (8kB) and triples upward, so a 116MB table ends up eight triplings from the start, producing nine workers instead of the expected serial plan. On a two-core instance this turned a 10ms serial count(*) over a 9.6MB table into 33-37ms with seven workers, since the regression test setting of 0 is meant for toy tables, not production.

_Debugging unexpected parallel plan regressions gets easier when you track configuration gotchas like this via daily.dev._

### How does CREATE INDEX use min_parallel_table_scan_size differently from a regular query plan?

CREATE INDEX reads the session's min_parallel_table_scan_size and climbs the same tripling ladder to decide how many parallel workers to request for the build. Raising this value in postgresql.conf to keep small queries serial also forces index builds on tables below that threshold to run serially, including every index built during a pg_restore, so it should be set per-role rather than globally.

_Planning index build performance or pg_restore timing benefits from tracking these planner interactions on daily.dev._

## Similar posts on daily.dev

- [All Your GUCs in a Row: max\_parallel\_workers and max\_parallel\_workers\_per\_gather](https://daily.dev/posts/all-your-gucs-in-a-row-max-parallel-workers-and-max-parallel-workers-per-gather-glgptdm34) · Planet PostgreSQL · 0 upvotes · 0 comments
- [All Your GUCs in a Row: max\_parallel\_maintenance\_workers](https://daily.dev/posts/all-your-gucs-in-a-row-max-parallel-maintenance-workers-autwoeu1a) · Planet PostgreSQL · 0 upvotes · 0 comments
- [All Your GUCs in a Row: enable\_indexscan and enable\_bitmapscan](https://daily.dev/posts/all-your-gucs-in-a-row-enable-indexscan-and-enable-bitmapscan-cifajzmnh) · Planet PostgreSQL · 0 upvotes · 0 comments
- [All Your GUCs in a Row: enable\_parallel\_hash](https://daily.dev/posts/all-your-gucs-in-a-row-enable-parallel-hash-xmfdenbk2) · Planet PostgreSQL · 0 upvotes · 0 comments
- [My queries to monitor autovacuum](https://daily.dev/posts/my-queries-to-monitor-autovacuum-vscqbjwpm) · CYBERTEC PostgreSQL · 0 upvotes · 0 comments

---

Tags: [#database](https://daily.dev/tags/database), [#postgresql](https://daily.dev/tags/postgresql)

[View this post on daily.dev](https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"All Your GUCs in a Row: min_parallel_index_scan_size and min_parallel_table_scan_size","url":"https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum"},"datePublished":"2026-10-03T01:02:15.640Z","dateModified":"2026-10-03T01:02:39.150Z","description":"A deep dive into two PostgreSQL planner GUCs, min_parallel_table_scan_size (default 8MB) and min_parallel_index_scan_size (default 512kB), explaining how they...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/8978e6eb3c0b3a2efa6b68437bd22e51?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/8978e6eb3c0b3a2efa6b68437bd22e51?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Planet PostgreSQL","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Planet PostgreSQL","logo":"https://media.daily.dev/image/upload/logos/placeholder.jpg","url":"https://daily.dev/sources/planet-postgresql"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"database,postgresql","timeRequired":"PT7M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Planet PostgreSQL","item":"https://daily.dev/sources/planet-postgresql"},{"@type":"ListItem","position":3,"name":"All Your GUCs in a Row: min_parallel_index_scan_size and min_parallel_table_scan_size"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/all-your-gucs-in-a-row-min-parallel-index-scan-size-and-min-parallel-table-scan-size-kzuffquum#faq","mainEntity":[{"@type":"Question","name":"What does min_parallel_table_scan_size actually control in PostgreSQL's query planner?","acceptedAnswer":{"@type":"Answer","text":"It sets the minimum table size, 8MB by default, below which a scan is not even considered for a parallel plan, but it also serves as the starting point of the tripling ladder the planner climbs to decide worker counts: one worker at that size, another each time the estimated table size triples, capped by max_parallel_workers_per_gather. Lowering it stretches the ladder and can hand more workers to small tables. Anyone tuning parallel query behavior can keep notes like this handy by following PostgreSQL deep dives on daily.dev."}},{"@type":"Question","name":"Why does setting min_parallel_table_scan_size to 0 in PostgreSQL cause too many parallel workers on small tables?","acceptedAnswer":{"@type":"Answer","text":"Setting it to 0 does not remove the minimum entirely; the planner floors the starting point at one block (8kB) and triples upward, so a 116MB table ends up eight triplings from the start, producing nine workers instead of the expected serial plan. On a two-core instance this turned a 10ms serial count(*) over a 9.6MB table into 33-37ms with seven workers, since the regression test setting of 0 is meant for toy tables, not production. Debugging unexpected parallel plan regressions gets easier when you track configuration gotchas like this via daily.dev."}},{"@type":"Question","name":"How does CREATE INDEX use min_parallel_table_scan_size differently from a regular query plan?","acceptedAnswer":{"@type":"Answer","text":"CREATE INDEX reads the session's min_parallel_table_scan_size and climbs the same tripling ladder to decide how many parallel workers to request for the build. Raising this value in postgresql.conf to keep small queries serial also forces index builds on tables below that threshold to run serially, including every index built during a pg_restore, so it should be set per-role rather than globally. Planning index build performance or pg_restore timing benefits from tracking these planner interactions on daily.dev."}}]}
```

