03 / 05

How do you manage database transactions correctly in Go, including error handling?

Difficulty: 6/10
sql.Tx, error handling, context

Begin a transaction, defer a rollback immediately, execute queries with error checking, and commit at the end. The deferred rollback is a no-op if Commit has already been called.

Correct transaction pattern
Transaction best practices
  1. 1

    Defer Rollback immediately after BeginTx — ensures rollback on any error path

  2. 2

    Pass tx as a DBTX interface to repository functions for unit-of-work reuse

  3. 3

    Keep transactions short — long-running transactions hold locks and cause contention

  4. 4

    Handle serialization failures (pgcode 40001) with retry logic for high-contention scenarios

  5. 5

    Use savepoints for nested transaction-like behavior within a single transaction

Scenario Questions

0-2 years experience

  1. 1Imagine you need to insert a new user and their profile in two tables atomically. How would you write the Go code using a transaction and ensure errors are handled correctly?
  2. 2If Exec returns an error inside a transaction, what steps must you take before returning from the function?
  3. 3What does defer tx.Rollback() do, and why is it safe to call even after a successful Commit?

2-5 years experience

  1. 1You added a new feature that writes to three tables inside a transaction, but occasional deadlocks appear in production. How would you investigate and mitigate the issue?
  2. 2During a code review you notice that a function starts a transaction but returns without calling Commit or Rollback in some error paths. What problems could arise and how would you fix it?
  3. 3Explain how you would propagate transaction errors up the call stack while preserving context for logging.

5-8 years experience

  1. 1Our service processes high‑volume financial orders and uses a single transaction per request. What design changes would you consider to improve throughput while maintaining ACID guarantees?
  2. 2We need to support nested operations that sometimes require their own rollback without affecting the outer transaction. How would you implement this in Go given the standard library’s limitations?
  3. 3Discuss the trade‑offs between using database‑level savepoints versus application‑level compensating actions for partial failures.

8+ years experience

  1. 1We are migrating from a monolithic Go service with manual transaction handling to a microservice architecture with shared data stores. How would you design a strategy to ensure transaction consistency across services?
  2. 2Our organization wants to standardize transaction handling across multiple teams and databases (Postgres, MySQL). What guidelines and abstractions would you propose, and how would you enforce them?
  3. 3Consider a scenario where a long‑running batch job must process millions of rows with transactional guarantees. How would you architect the job to avoid locking issues and enable graceful recovery after failures?

Follow-up Questions

  • What would happen if you forget to check the error returned by Commit?
  • How would you handle a downstream service failure that occurs after you have already committed the transaction?
  • Why would you pass a context with timeout when starting a transaction?
Share

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.