Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

createVersion / createGlobalVersion rewrite every older version's latest flag on each save

Open Beginner friendly
#18,465 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@frammawiliansyah is already working on this.

Since Oct 3, 2026.

  • #18472 by @frammawiliansyah — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
nodejs, postgresql, typescript

Research direction

Start with packages/drizzle/src/createVersion.ts and packages/drizzle/src/createGlobalVersion.ts, then inspect the shared database tests for version saves across Postgres, SQLite, and D1. Reproduce a document or global version save with many older versions and verify that only the currently latest row is rewritten while the final latest state remains unchanged.

Written by the indexing model from the issue text.

Description

Bug db: drizzle (also sqlite and d1 db: postgres which share the code)
Describe the Bug

On every save of a document with drafts, @payloadcms/drizzle's createVersion sets latest = false on every older version of that document, not just the one that is currently latest:

UPDATE <versions>
SET latest = false
WHERE id != $new
  AND parent_id = $parent
  AND updated_at < $now

Only one older row is ever latest = true. All the others are already false, but they are rewritten anyway. Because latest is indexed, each rewrite is a full (non-HOT) row update.

On Postgres, for a document with 100 versions (maxPerDoc: 100), we measured:

  • Today: 100 rows updated per save, about 1,450 buffers, 9–10 ms.
  • With AND latest IS NOT FALSE added: 1 row updated, 0.4 ms.

The final state is the same, because rows that are already false stay false.

createGlobalVersion has the same pattern with no other condition (WHERE id != $new), so a global rewrites every version row on each save.

Possibly related: #17216 (duplicate latest rows under autosave on D1/SQLite). That issue is about correctness; this one is about cost. Narrowing the UPDATE to the row that is actually latest would also make the statement much smaller for that case.

Link to the code that causes the issue

packages/drizzle/src/createVersion.ts and packages/drizzle/src/createGlobalVersion.ts (seen in 3.89.0, still present in 3.90.2).

Reproduction Steps
  1. Create a collection with versions: { drafts: true, maxPerDoc: 100 } on @payloadcms/db-postgres.
  2. Save one document 100 times.
  3. Save it again with Postgres statement logging, or EXPLAIN (ANALYZE, BUFFERS) the UPDATE above. It updates about 100 rows, where 1 would do.

Suggested fix, which we run as a local patch:

         WHERE ${table.id} != ${result.id}
           AND ${table.parent} = ${parent}
           AND ${table.updatedAt} < ${result.updatedAt || updatedAt}
+          AND ${table.latest} IS NOT FALSE

The same condition would apply to createGlobalVersion.

Which area(s) are affected?

db: postgres, db: drizzle (also sqlite and d1, which share the code)

Environment Info
payload: 3.89.0 (code unchanged in 3.90.2)
@payloadcms/db-postgres: 3.89.0
Database: PostgreSQL 16 (AWS RDS)
Node: 22
Dominant language
TypeScript
Stars
45.5k
Forks
4.3k
Avg merge
1d 22h
Merged PRs (30d)
312

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from payloadcms/payload

All issues in payloadcms/payload

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.