Skip to content

Conversation

@roji
Copy link
Member

@roji roji commented Oct 30, 2025

#3646 reported a memory leak: when NpgsqlDatabaseCreateor.Exists() is called (from DatabaseFacadeExtensions.CanConnect()), it was using NpgsqlConnection.CloneWith() to create a new, unpooled connection, which it then tried to connect to the database. The problem is, the cloned connection doesn't use an explicit data source, meaning that a data source is internally created inside Npgsql, referenced by the internal static dictionary. If the password continuously changes (rotating auth tokens), that led to increasing memory use which never gets freed.

This is ultimately npgsql/npgsql#3387: we should be able to call ClearPool() on the cloned connection to have it unreference the internal data source, allowing it to get garbage collected - though in theory, a real user in the application might be using the same connection string, which EF would then cause to get cleared; while quite contrived, it shows how bad the legacy connection mechanism is.

This PR simply changes to sending SELECT 1 to the database, which is what the SQL Server provider does as well. This does have the drawback of returning "exists" (and also "can connect") even when e.g. the password has changed (because there are pooled connections which allow executing SELECT 1), but that's seems like an unimportant edge case (the same pooled connections will be there for actual usage etc.). And the CloneWith() mechanism here has been the source of lots of trouble over the years, without adding much real value.

This also adds the execution strategy to Exists(), which allows retrying on transient errors.

Fixes #3646

Thanks @vonzshik for the initial investigation.

@roji roji merged commit 3e175da into npgsql:main Oct 30, 2025
14 checks passed
@roji roji deleted the ExistsLeak branch October 30, 2025 08:35
roji added a commit that referenced this pull request Oct 30, 2025
@roji
Copy link
Member Author

roji commented Oct 30, 2025

Backported to 9.0.5 via 36d5508
Backported to 8.0.12 via 3bb3109

roji added a commit that referenced this pull request Oct 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory Leak on NpgsqlDataSource with password provider

1 participant