Você pode definir um gatilho para manter o número da linha desejado:
CREATE OR REPLACE FUNCTION trf_keep_row_number_steady()
RETURNS TRIGGER AS
$body$
BEGIN
-- delete only where are too many rows
IF (SELECT count(id) FROM log_table) > rownum_limit
THEN
-- I assume here that id is an auto-incremented value in log_table
DELETE FROM log_table
WHERE id = (SELECT min(id) FROM log_table);
END IF;
END;
$body$
LANGUAGE plpgsql;
CREATE TRIGGER tr_keep_row_number_steady
AFTER INSERT ON log_table
FOR EACH ROW EXECUTE PROCEDURE trf_keep_row_number_steady();
Provavelmente, essa não é a opção com melhor desempenho, mas quando você atingir o limite, nunca será excedido. Se houver espaço para flutuação, você poderá verificar o número da linha periodicamente e excluir linhas em excesso desde o início.
EDIT:
Se você tiver logs realmente grandes (digamos um milhão por mês), o particionamento pode ser a solução mais fácil. Você pode simplesmente soltar as tabelas desnecessárias (digamos ondemax(timestamp) < CURRENT_DATE - 1 year
). Você pode usar seu carimbo de data / hora (ou uma data derivada) como condição para o particionamento de intervalo .
Mas tenha cuidado antes de descartar logs antigos. Tem certeza de que nunca precisará disso?