Your Index Only Scan Is Lying: Covering Indexes and the Visibility Map
A covering index contains every column a query reads, so the database answers entirely from the index without visiting the table. In Postgres, the INCLUDE clause adds payload columns to leaf pages — they can't be searched or sorted on, but they eliminate the heap fetch that makes index scans expensive.
The catch: Postgres index-only scans depend on the visibility map. Each heap page has an all-visible bit set by VACUUM. If a page was recently modified and VACUUM hasn't caught up, the engine falls back to fetching the heap anyway. Heap Fetches in EXPLAIN ANALYZE is your diagnostic — any positive number means degraded pages. InnoDB doesn't have this problem because row versions live in the clustered index directly.
Covering indexes shine on hot read paths with stable data. On write-heavy tables where the visibility map can't stay current, you're paying index maintenance costs for a benefit that never materialises. Check Heap Fetches before celebrating that Index Only Scan.