Skip to content

Preserve a statement cache size of 0 - #22767

Merged
desertaxle merged 2 commits into
PrefectHQ:mainfrom
ckarnell:fix/statement-cache-size-zero
Aug 10, 2026
Merged

Preserve a statement cache size of 0#22767
desertaxle merged 2 commits into
PrefectHQ:mainfrom
ckarnell:fix/statement-cache-size-zero

Conversation

@ckarnell

Copy link
Copy Markdown
Contributor

AsyncPostgresConfiguration.__init__ resolves both cache-size arguments with or:

self.statement_cache_size = statement_cache_size or <setting>

0 is falsy, so it gets replaced by the setting, which defaults to None. The if ... is not None further down then skips the key entirely and asyncpg keeps its cache at the default.

Your own settings say 0 is the value that matters. statement_cache_size is documented as "Setting this to 0 is required when using PgBouncer in transaction mode", and prepared_statement_cache_size as disabling the cache "when set to 0". The or discards exactly the value both descriptions name as the reason to reach for the setting.

Switched to is not None at both sites. Two lines.

The scope is narrow, and saying so up front seems better than letting it read bigger than it is: passing 0 through settings already worked, because the constructor argument is None on that path, and prefect itself only ever builds this class from a connection URL. So the person affected is someone wiring up AsyncPostgresConfiguration themselves to sit behind PgBouncer, which is who the docstring is talking to.

Verified with no database and no network, just the constructor. On main, statement_cache_size=0 comes back as None while statement_cache_size=100 comes back as 100, and the same split happens for the prepared cache. The same call keeps the non-zero value and drops the zero.

Reverting the two lines with the new tests in place fails them both, and restoring passes all four. tests/server/database is 97 passed and 7 skipped with the change, against 93 before it, no regressions either way.

No PgBouncer here. The claim that 0 reaches asyncpg is read off connect_args, not observed on a live connection.

AsyncPostgresConfiguration resolves both cache-size arguments with `or`:

    self.statement_cache_size = statement_cache_size or <setting>

0 is falsy, so it is replaced by the setting, which defaults to None. The
key is then never added to connect_args and asyncpg keeps its cache.

0 is not an absent value for either of these, and the settings that back
them say so. statement_cache_size: "Setting this to 0 is required when
using PgBouncer in transaction mode." prepared_statement_cache_size:
"When set to 0, statement caching is disabled." So `or` discards exactly
the value the documentation gives as the reason to set them.

Resolve with `is None` instead. Passing 0 through the settings already
worked, because the argument is None there and the setting is consulted;
only callers constructing the configuration directly were affected.

Non-zero values were already preserved and still are; the tests cover
both so the fix cannot be read as special-casing zero.
@codspeed-hq

codspeed-hq Bot commented Aug 10, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 8 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing ckarnell:fix/statement-cache-size-zero (ff1dd63) with main (fc2add9)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

@desertaxle desertaxle left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ckarnell! Looks like there's one small formatting issue, but once that's fixed, this should be good to merge!

The pre-commit ruff-format hook (pinned v0.15.19) strips a trailing blank
line at the end of the test file this branch adds. Taking the formatter's
output; ruff check was already clean and the four tests still pass.
@ckarnell

Copy link
Copy Markdown
Contributor Author

Fixed, thanks. It was a trailing blank line at the end of the test file, which ruff-format strips at the hook pin.

Worth flagging since it caught me out: pyproject.toml pins ruff==0.16.0 but the pre-commit hook is v0.15.19, and the hook is what CI runs. I checked against 0.15.19.

@desertaxle
desertaxle merged commit d83c90f into PrefectHQ:main Aug 10, 2026
93 checks passed
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.

2 participants