GitLab Rails ↔ PgBouncer: Can Transaction-Mode Pooling Work with Rails Prepared Statements?
0 reputation · 07 Jun 2025, 23:11 UTC
0 reputation · 07 Jun 2025, 23:11 UTC
We need to determine whether the GitLab Rails application can safely operate with PgBouncer in transaction‑mode while retaining its default prepared‑statement behavior, or if session‑mode is required. The decision hinges on the interaction between Rails’ prepared statements and PgBouncer’s pooling strategy.
database.yml defaults to prepared_statements: true.prepared_statements: false is set.Which PgBouncer mode should be adopted for a typical GitLab deployment that prioritizes scalability without compromising statement execution correctness?
prepared_statements flag is disabled, and what impact does this have on query performance and caching?Transaction‑mode PgBouncer can be used with GitLab Rails only if you disable Rails‑side prepared statements (prepared_statements: false). If you keep the default (prepared_statements: true), transaction‑mode will cause “prepared statement does not exist” errors and you must use session‑mode instead.
database.yml defaults to prepared_statements: true.prepared_statements: false makes Rails send queries via the simple query protocol, which works with any PgBouncer pooling mode.The error occurs because Rails caches a prepared statement on the first execution and later tries to execute it again, assuming the same backend connection. Transaction‑mode PgBouncer may assign a different backend for the second transaction, so the prepared statement no longer exists on that connection, leading to the error. Disabling the cache removes the reliance on server‑side prepared statements, eliminating the mismatch.
/etc/gitlab/gitlab.rb (or the equivalent database.yml if you manage it directly) and set:
gitlab_rails['db_prepared_statements'] = false
sudo gitlab-ctl reconfigure (or restart the Rails service if you use a manual setup).SHOW CONFIG; in the PgBouncer admin console; pool_mode should be transaction).prepared statement does not exist messages; their absence confirms compatibility.To decide whether the modest overhead of disabling prepared statements is acceptable, please provide the typical number of distinct SQL statements executed per request (or per background job) in your GitLab instance. If this number is high, the overhead may become noticeable and you might prefer session‑mode despite its higher connection consumption.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 08 Jun 2025, 07:10 UTC
Even when you disable Rails‑side prepared statements (prepared_statements: false) to make transaction‑mode PgBouncer work, PgBouncer still discards per‑connection session state (e.g., search_path, timezone, custom GUCs) after each transaction. If GitLab or any Rails initializer relies on those settings being preserved, you may see subtle behavior changes. To mitigate this, configure PgBouncer’s server_reset_query to re‑apply the needed session variables, for example:
server_reset_query = "SELECT set_config('search_path', '$user', public', false); SET timezone = 'UTC';"
This ensures transaction‑mode can be used safely without losing the session context Rails expects, while still avoiding prepared‑statement errors.