go-database
Database patterns for Go services: database/sql, connection management, transactions, migrations, query builders, and ORM usage (sqlc, GORM, ent). Use when: "database access", "SQL query", "connection pool", "transactions", "database migration", "sqlc", "GORM", "ent", "prepared statement", "repository pattern". Not for: in-memory structures (go-data-structures), SQL security (go-security-audit), query profiling (go-performance-review).
How do I install this agent skill?
npx skills add https://github.com/eduardo-sl/go-agent-skills --skill go-databaseIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides best practice patterns and guidelines for Go database development, including connection pool management, transaction handling, and repository patterns. No malicious behavior or security risks were detected.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Go Database Patterns
Database access is where most Go services spend their complexity budget. Get connection management, transactions, and query patterns right.
Detailed reference material, loaded on demand:
references/query-patterns.md— full query/scan/rows patterns, null handling, N+1 avoidance, connection-leak examples.references/tooling.md— repository pattern implementation, sqlc annotated queries, migration tooling and rules.
Read a reference file only when the summary below is not enough.
1. Connection Management
Configure the pool explicitly — the default is unbounded connections:
func OpenDB(dsn string) (*sql.DB, error) {
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, fmt.Errorf("open db: %w", err)
}
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(5 * time.Minute)
db.SetConnMaxIdleTime(1 * time.Minute)
if err := db.PingContext(context.Background()); err != nil {
return nil, fmt.Errorf("ping db: %w", err)
}
return db, nil
}
| Setting | Guideline |
|---|---|
MaxOpenConns | Match your DB's max connections / number of app instances |
MaxIdleConns | 40-50% of MaxOpenConns |
ConnMaxLifetime | 5-10 minutes (prevents stale connections behind load balancers) |
ConnMaxIdleTime | 1-2 minutes |
2. Query Rules
- Parameterized queries only — string concatenation into SQL is an injection vulnerability, no exceptions.
- Always pass context — use the
*Contextvariants (QueryContext,QueryRowContext,ExecContext) so queries respect cancellation and timeouts. defer rows.Close()immediately after the error check, and checkrows.Err()after the iteration loop.- Handle
sql.ErrNoRowsexplicitly witherrors.Is, mapping it to a domain error likeErrUserNotFound.
var user User
err := db.QueryRowContext(ctx,
"SELECT id, name, email FROM users WHERE id = $1", id,
).Scan(&user.ID, &user.Name, &user.Email)
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrUserNotFound
}
if err != nil {
return nil, fmt.Errorf("get user %s: %w", id, err)
}
Multi-row iteration patterns: references/query-patterns.md.
3. Transactions
Use a helper that guarantees rollback on error:
func WithTx(ctx context.Context, db *sql.DB, fn func(tx *sql.Tx) error) error {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("begin tx: %w", err)
}
if err := fn(tx); err != nil {
if rbErr := tx.Rollback(); rbErr != nil {
return fmt.Errorf("rollback failed: %v (original: %w)", rbErr, err)
}
return err
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("commit tx: %w", err)
}
return nil
}
Set isolation explicitly for critical operations:
sql.TxOptions{Isolation: sql.LevelSerializable}.
4. Structure and Tooling
- Repository pattern: define the interface at the consumer side, implement it with concrete database access, map driver errors to domain errors at this boundary.
- sqlc: prefer it for raw-SQL projects — generates type-safe Go from annotated SQL, catching query/schema mismatches at build time.
- Migrations: use a tool (
goose,golang-migrate,atlas), one migration per change, forward-only in production, withdownSQL, run as a separate step — not at server startup.
Implementations and examples: references/tooling.md.
5. Common Pitfalls
- Null columns: use
sql.NullString/sql.NullInt64or pointer fields (*string, nil = SQL NULL). Scanning NULL into a plain string errors at runtime. - N+1 queries: a query inside a loop over query results. Replace
with a JOIN or a batch query (
WHERE id = ANY($1)). - Connection leaks: any early
returnbetweenQueryanddefer rows.Close()leaks a connection from the pool.
Worked examples of each pitfall: references/query-patterns.md.
Verification Checklist
- Connection pool configured with explicit limits (
MaxOpenConns,MaxIdleConns, lifetimes) - All queries use parameterized placeholders, never string concatenation
- All
QueryContextresults havedefer rows.Close()immediately after error check rows.Err()checked after row iteration loopsql.ErrNoRowshandled explicitly witherrors.Is- Transactions use a helper that guarantees rollback on error
- Context propagated to all database calls (
*Contextvariants) - Nullable columns use
sql.NullString/sql.NullInt64or pointer types - No N+1 query patterns — use JOINs or batch queries
- Migrations are versioned, reversible, and run separately from app startup
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/eduardo-sl/go-agent-skills/go-database">View go-database on skillZs</a>