In genere sei sulla strada giusta e la tua analisi sembra accurata. Alcuni commenti:
L'opzione 2 (risultando keepalive) aiuterà a rimuovere le connessioni inattive nel pool di Npgsql che sono state interrotte. Come hai scritto, la tua applicazione presenterà ancora alcuni errori (poiché alcune cattive connessioni inattive potrebbero non essere rimosse in tempo). Non vi è alcun motivo particolare per pensare che ciò possa causare ulteriori problemi:l'attivazione dovrebbe essere abbastanza sicura.
L'opzione 3 è effettivamente problematica per perf, poiché una connessione TCP a pgbouncer dovrebbe essere stabilita ogni volta che è necessaria una connessione al database. Inoltre, non fornirà un meccanismo a prova di errore al 100%, poiché pgbouncer potrebbe comunque interrompersi mentre è in uso una connessione.
Alla fine della giornata, ti stai chiedendo della resilienza di fronte a un errore arbitrario di rete/server, che non è una cosa facile da ottenere. L'unico modo affidabile al 100% per gestire questo problema è nell'applicazione, tramite un livello dedicato che ritenterebbe le operazioni quando si verifica un'eccezione transitoria. Potresti voler dare un'occhiata a Polly
e nota che Npgsql ci aiuta un po' esponendo un IsTransient
eccezione che può essere utilizzata come trigger per riprovare (Entity Framework Core include anche una "strategia di ripetizione" simile). Se segui questo percorso, tieni presente che le transazioni sono particolarmente difficili da gestire correttamente.