Enabling prepared statements globally
SetPrepareStmt: true in gorm.Config when opening the database:
Find, Create, Update, and Delete — automatically goes through the prepared statement cache.
Enabling prepared statements per session
If you only want prepared statements for a subset of operations, enable them on a session:db already has a cache, the session attaches to it rather than creating a new one.
Cache configuration
LRU cache size
The maximum number of prepared statements the cache holds at one time. When the limit is reached, the least recently used statement is closed and removed before the new one is added.Keep this value proportional to your query diversity. A limit that is too small causes frequent eviction and re-preparation, negating the performance benefit.
Cache TTL
How long a cached statement is considered valid. After the TTL elapses the entry is evicted, and the SQL is re-prepared on the next use.A shorter TTL reduces the risk of holding stale prepared statements after schema changes, but increases re-preparation frequency.
How the cache works
The cache is backed byPreparedStmtDB, which wraps a ConnPool and intercepts every ExecContext, QueryContext, and QueryRowContext call:
- The SQL string is used as the cache key.
- An
RLockis acquired to check whether the statement already exists in the store. - If found and valid, the cached
*sql.Stmtis used directly. - If not found, the lock is promoted to a write lock, the statement is prepared via the underlying
ConnPool, and the result is stored. - If the driver returns
driver.ErrBadConn, the cache entry is deleted so it will be re-prepared on the next attempt.
Transactions
Inside a transaction, GORM automatically switches fromPreparedStmtDB to PreparedStmtTX, which wraps the transaction’s Tx interface:
PreparedStmtTX calls tx.StmtContext to bind each cached statement to the current transaction before executing it, which is required by database/sql.
Closing and resetting the cache
CallClose on the PreparedStmtDB to release all cached statements:
Close acquires the write lock, iterates over all cached statement keys, and deletes each one from the store. After calling Close, the cache is empty and new statements will be re-prepared on the next use.
Reset() is a deprecated alias for Close(). Use Close() in new code.Performance considerations
When prepared statements help most
When prepared statements help most
Prepared statements have the greatest impact when:
- The same SQL shape is executed many times (e.g., point lookups by primary key).
- The database’s query planner is relatively expensive (common in PostgreSQL).
- Connection pooling reuses connections long enough for cached statements to be used repeatedly.
Prepared statements and schema changes
Prepared statements and schema changes
Prepared statements are compiled against the schema at the time of preparation. If you run a migration that changes a table used by a cached statement (adding a column, changing a type), the cached statement may become stale.Mitigate this by:
- Calling
pdb.Close()after running migrations to flush the cache. - Setting a short
PrepareStmtTTLif schema changes happen frequently. - Disabling prepared statements during migration sessions.
Cache size tuning
Cache size tuning
A rough starting point for
PrepareStmtMaxSize is the number of distinct SQL patterns your application generates. You can estimate this by:- Running with
PrepareStmt: trueand no size limit. - Observing how many entries accumulate in the cache during a representative load test.
- Setting
PrepareStmtMaxSizeto 110–120% of that observed count to allow headroom.
Types reference
PreparedStmtDB
PreparedStmtDB is the cached connection pool that replaces db.ConnPool when PrepareStmt is enabled globally.
| Method | Description |
|---|---|
ExecContext | Prepares (or retrieves) and executes a statement |
QueryContext | Prepares (or retrieves) and queries rows |
QueryRowContext | Prepares (or retrieves) and queries a single row |
BeginTx | Starts a transaction, returning a PreparedStmtTX |
GetDBConn | Returns the underlying *sql.DB |
Close | Closes and removes all cached statements |
Ping | Delegates to the underlying connection pool |
PreparedStmtTX
PreparedStmtTX wraps an active *sql.Tx and binds cached statements to the transaction context before execution.
| Method | Description |
|---|---|
ExecContext | Binds cached statement to tx and executes |
QueryContext | Binds cached statement to tx and queries rows |
QueryRowContext | Binds cached statement to tx and queries one row |
Commit | Commits the transaction |
Rollback | Rolls back the transaction |
GetDBConn | Returns the underlying *sql.DB |