Документация PostgreSQL о типах serial явно говорит об этом:
Note
Because smallserial, serial and bigserial are implemented using
sequences, there may be "holes" or gaps in the sequence of values
which appears in the column, even if no rows are ever deleted. A value
allocated from the sequence is still "used up" even if a row
containing that value is never successfully inserted into the table
column. This may happen, for example, if the inserting transaction
rolls back. See nextval() in Section 9.17 for details.
Вольный перевод:
Заметка
Поскольку smallserial, serial и bigserial используют
последовательности sequences, они могут оставлять "дыры" или пропуски
значений для колонки, даже если строки не были удалены. Значение в
последовательности растет, даже если полученное из неё значение не
используется успешно при вставке. К примеру, если транзакция на
вставку откатилась. Смотрите Section 9.17 для подробностей.
Ну и секция 9.17 говорит о том, что последовательности созданы так, чтобы не блокировать параллельные транзакции во время выполнения. Поэтому значение, полученное из nextval не восстанавливается обратно.
Вообще закладываться на автоинкрементное поле ID и что его последовательности будут идти друг за другом по порядку является плохой идеей. Если вам все же очень это нужно, то придется отказаться от этих типов и использовать свои костыли реализации.