diff --git a/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs b/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs
index 3f464dd97..651130fc9 100644
--- a/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs
+++ b/src/Orbit.Infrastructure/Persistence/OrbitConnectionStringFactory.cs
@@ -11,7 +11,9 @@ namespace Orbit.Infrastructure.Persistence;
/// migrations, the design-time factory, and the Hangfire durable queue use
/// ConnectionStrings:SessionConnection (the session pooler), falling back to
/// DefaultConnection when it is unset. The configured
-/// pool caps override any pool size present in the raw connection string.
+/// pool caps override any pool size present in the raw connection string. Idle session-pool connections
+/// are pruned after 60 seconds, and open inactive session connections receive keepalive queries after
+/// 30 seconds to detect connections closed by the pooler or network.
///
public static class OrbitConnectionStringFactory
{
@@ -28,7 +30,15 @@ public static string ForSession(IConfiguration configuration)
if (string.IsNullOrWhiteSpace(sessionConnectionString))
sessionConnectionString = configuration.GetConnectionString("DefaultConnection");
- return ApplyPoolCap(sessionConnectionString, settings.SessionMaxPoolSize);
+ var cappedConnectionString = ApplyPoolCap(sessionConnectionString, settings.SessionMaxPoolSize);
+ if (string.IsNullOrEmpty(cappedConnectionString))
+ return cappedConnectionString;
+
+ return new NpgsqlConnectionStringBuilder(cappedConnectionString)
+ {
+ ConnectionIdleLifetime = 60,
+ KeepAlive = 30
+ }.ConnectionString;
}
private static string ApplyPoolCap(string? connectionString, int maxPoolSize)
diff --git a/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs b/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs
index a75ac180a..f27901425 100644
--- a/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs
+++ b/tests/Orbit.Infrastructure.Tests/Persistence/OrbitConnectionStringFactoryTests.cs
@@ -54,6 +54,9 @@ public void ForSession_PrefersSessionConnection_OverDefault()
result.Host.Should().Be("session");
result.Port.Should().Be(5432);
result.MaxPoolSize.Should().Be(5);
+ result.MinPoolSize.Should().Be(0);
+ result.ConnectionIdleLifetime.Should().Be(60);
+ result.KeepAlive.Should().Be(30);
}
[Theory]