Pool Configuration
Configure database connection pool settings — MaxOpenConns, MaxIdleConns, and ConnMaxLifetime — with recommended values for different workloads.
Pool Configuration
Go's database/sql package maintains a connection pool for each database. go-migration exposes these pool settings through ConnectionConfig so you can tune them per connection.
Pool Settings
Configure pool behavior when adding a connection:
mgr.AddConnection("primary", database.ConnectionConfig{
Driver: "postgres",
Host: "localhost",
Port: 5432,
Database: "myapp",
Username: "user",
Password: "pass",
MaxOpenConns: 25,
MaxIdleConns: 5,
ConnMaxLifetime: 5 * time.Minute,
Options: map[string]string{"sslmode": "disable"},
})go-migration only applies a pool setting when its value is greater than zero. Leaving a field at its zero value keeps Go's database/sql default for that setting — go-migration does not impose its own defaults. When configuring via a JSON/YAML file, conn_max_lifetime must be a duration string such as "5m" (a bare number is interpreted as nanoseconds).
MaxOpenConns
Sets the maximum number of open connections to the database (both in-use and idle).
MaxOpenConns: 25- Default:
0(unlimited) - When the limit is reached, new queries block until a connection becomes available
- Set this to prevent overwhelming your database server
- On PostgreSQL and MySQL, keep it at
0or at least2for any pool the migrator uses (see below)
The migration lock needs two connections. Up, Rollback, Reset, Refresh, Fresh, and the CLI's migrate:install and db:seed* commands hold a session-level lock (PostgreSQL advisory lock, MySQL GET_LOCK) on a dedicated connection taken from the pool, while the migrations run on another. With locking enabled on PostgreSQL or MySQL, a pool limited to one connection (MaxOpenConns: 1) is rejected with an error rather than deadlocking — raise the limit, or disable locking with migrator.WithoutLock() / --no-lock. SQLite takes no lock, so MaxOpenConns: 1 is fine there. See Concurrency and Locking.
MaxIdleConns
Sets the maximum number of idle connections kept in the pool.
MaxIdleConns: 5- Default:
2(this is Go'sdatabase/sqldefault; go-migration does not set it) - Idle connections are reused for new queries, avoiding the overhead of opening a new connection
- Should be less than or equal to
MaxOpenConns
ConnMaxLifetime
Sets the maximum amount of time a connection can be reused before it's closed and replaced.
ConnMaxLifetime: 5 * time.Minute- Default:
0(no limit) - Helps cycle connections through load balancers and prevents stale connections
- Set this lower than any database-side connection timeout
These settings map directly to Go's *sql.DB methods: SetMaxOpenConns(), SetMaxIdleConns(), and SetConnMaxLifetime().
Recommended Values
For a typical web application handling concurrent HTTP requests:
mgr.AddConnection("web", database.ConnectionConfig{
Driver: "postgres",
Host: "localhost",
Port: 5432,
Database: "myapp",
Username: "user",
Password: "pass",
MaxOpenConns: 25,
MaxIdleConns: 10,
ConnMaxLifetime: 5 * time.Minute,
Options: map[string]string{"sslmode": "disable"},
})| Setting | Value | Rationale |
|---|---|---|
MaxOpenConns | 25 | Handles concurrent requests without overwhelming the database |
MaxIdleConns | 10 | Keeps warm connections ready for bursts |
ConnMaxLifetime | 5 min | Cycles connections to stay fresh behind load balancers |
For background job processors with lower concurrency:
mgr.AddConnection("worker", database.ConnectionConfig{
Driver: "postgres",
Host: "localhost",
Port: 5432,
Database: "myapp",
Username: "user",
Password: "pass",
MaxOpenConns: 10,
MaxIdleConns: 5,
ConnMaxLifetime: 10 * time.Minute,
Options: map[string]string{"sslmode": "disable"},
})| Setting | Value | Rationale |
|---|---|---|
MaxOpenConns | 10 | Lower concurrency needs fewer connections |
MaxIdleConns | 5 | Moderate idle pool for steady throughput |
ConnMaxLifetime | 10 min | Longer lifetime since connections are used consistently |
For CLI tools and migration runners that run briefly:
mgr.AddConnection("cli", database.ConnectionConfig{
Driver: "postgres",
Host: "localhost",
Port: 5432,
Database: "myapp",
Username: "user",
Password: "pass",
MaxOpenConns: 5,
MaxIdleConns: 2,
ConnMaxLifetime: 1 * time.Minute,
Options: map[string]string{"sslmode": "disable"},
})| Setting | Value | Rationale |
|---|---|---|
MaxOpenConns | 5 | Minimal connections for short-lived processes — at least 2 are needed for the migration lock on PostgreSQL/MySQL |
MaxIdleConns | 2 | Small idle pool is sufficient |
ConnMaxLifetime | 1 min | Short lifetime since the process exits quickly |
Monitoring Pool Stats
You can inspect pool statistics at runtime using Go's built-in DBStats:
db, _ := mgr.Connection("primary")
stats := db.Stats()
fmt.Printf("Open connections: %d\n", stats.OpenConnections)
fmt.Printf("In use: %d\n", stats.InUse)
fmt.Printf("Idle: %d\n", stats.Idle)
fmt.Printf("Wait count: %d\n", stats.WaitCount)
fmt.Printf("Wait duration: %s\n", stats.WaitDuration)If WaitCount is consistently high, your MaxOpenConns may be too low for your workload. Increase it or optimize your queries to release connections faster.
What's Next?
- Drivers — set up PostgreSQL, MySQL, and SQLite drivers
- Connection Manager — manage multiple named connections