Обычно я решаю эту проблему с помощью триггера после таблицы, а затем вставляю старую строку вместе с отметкой времени и любой другой соответствующей информацией в другую таблицу аудита.
Итак, для примера, я бы создал таблицу users_audit.
таблица:
create table users_audit (
ts timestamptz default current_timestamp,
like users
);
А потом триггерная функция
create function users_audit_trigger() returns trigger
language plpgsql as $$
insert into users_audit values (current_timestamp, OLD.*);
$$
Наконец фактический триггер ...
create trigger users_audit_tg after update or delete on users
for each row execute procedure users_audit_trigger();
Выше не проверено, и вы можете войти в систему дополнительную информацию,
такие как пользователь, выполняющий обновление или фактическую операцию
обновить или удалить, так что детали, скорее всего, будут немного другими.
Вы можете использовать логическую репликацию для выполнения части или всего этого на другом
сервер, но основная идея остается прежней.