All original content is created in Ukrainian. Not all content has been translated yet. Some posts may only be available in Ukrainian.Learn more

Why does PostgreSQL skip IDs when saving new records? (Heroku)

Post cover: Why does PostgreSQL skip IDs when saving new records? (Heroku)
This content has been automatically translated from Ukrainian.
Checking the last ID in the database, and it is unexpectedly larger than the actual number of records. Why does this happen?
In Heroku (and generally in PostgreSQL), ID values can be non-sequential for several reasons:

Auto-increment field (serial / bigserial) and transactions

  • In Rails, IDs are usually serial or bigserial, which use SEQUENCE to generate unique values.
  • If a transaction that allocated an ID is rolled back (ROLLBACK), that value is no longer used, but the SEQUENCE continues to increment. For example, if an object is created with id = 4, and then the transaction is rolled back, the next record will receive id = 5, and 4 will remain skipped.

Concurrent queries

  • In cloud environments like Heroku, there can be many competing processes writing to the database simultaneously.
  • If two queries create new records at the same time, they may receive IDs in different orders.

Dyno restart (Heroku) and SEQUENCE caching

  • PostgreSQL caches SEQUENCE values, which helps improve performance.
  • If a Dyno (Heroku server) restarts, cached values may be lost, and PostgreSQL will skip several IDs.

Deleted records

  • If you delete records from a table (DELETE), their IDs are not reused.
  • For example, if there were records with IDs = 1, 2, 3, and then you deleted 2, the next ID will still be 4.

How to check SEQUENCE?

Run in the PostgreSQL console:
SELECT last_value, is_called FROM your_table_id_seq;
Or manually reset the value:
SELECT setval('your_table_id_seq', (SELECT MAX(id) FROM your_table));
This will align the SEQUENCE but will not fill gaps in already created IDs. This is normal behavior for PostgreSQL. If you critically need sequential IDs, you can use ROW_NUMBER(), but it is not recommended for primary IDs.

This post doesn't have any additions from the author yet.

What is Memoization (examples in Ruby and Ruby on Rails)?
20 Feb 18:16

What is Memoization (examples in Ruby and Ruby on Rails)?

meme code
meme code@memecode
What is debounce in JavaScript and why is it important?
21 Mar 16:39

What is debounce in JavaScript and why is it important?

meme code
meme code@memecode
What is CFB (Cipher Feedback)?
21 Mar 16:53

What is CFB (Cipher Feedback)?

meme code
meme code@memecode
What is XOR and how does it work?
21 Mar 17:05

What is XOR and how does it work?

meme code
meme code@memecode
Embedded programming: what it is and how to get started
24 Mar 16:48

Embedded programming: what it is and how to get started

meme code
meme code@memecode
Pessimistic Lock in Rails: what it is and when to use it. What are the alternatives?
31 Mar 17:45

Pessimistic Lock in Rails: what it is and when to use it. What are the alternatives?

meme code
meme code@memecode
[Codecov] What is the difference between patch and project coverage?
09 Apr 16:03

[Codecov] What is the difference between patch and project coverage?

meme code
meme code@memecode
How do Scratch courses help children develop soft skills?
11 Apr 18:24

How do Scratch courses help children develop soft skills?

meme code
meme code@memecode
24 Apr 20:17

Fixing minikube "You are trying to run the amd64 binary on an M1 system."

meme code
meme code@memecode
24 Apr 20:55

Fixing minikube on Mac with M1 (abandoning qemu, running on docker)

meme code
meme code@memecode
Where to find an older version of Google Chrome and download it? Using an old Mac as an example.
25 Apr 23:02

Where to find an older version of Google Chrome and download it? Using an old Mac as an example.

meme code
meme code@memecode
09 May 19:27

[FIXED] cannot load such file -- html/pipeline (LoadError) occurs during rails generate thredded:install

meme code
meme code@memecode