{
  "$type": "site.standard.document",
  "canonicalUrl": "https://rednafi.com/shards/2026/03/repository-layer-over-sqlc/",
  "description": "Decoupling business logic from storage with a small interface in Go.",
  "path": "/shards/2026/03/repository-layer-over-sqlc/",
  "publishedAt": "2026-03-16T00:00:00.000Z",
  "site": "at://did:plc:fgtm2c26vfcj74rfmeggbyqj/site.standard.publication/3mnl6f7ob462z",
  "tags": [
    "Go",
    "Database"
  ],
  "textContent": "Today in [r/golang], user Leading-West-4881 asked:\n\n> Is a repository layer over sqlc over-engineering or necessary for scale? I'm building a\n> notification engine in Go using sqlc for the DB layer. Do you just inject db.Queries\n> into your services, or do you find the abstraction of a repository layer worth the extra\n> code?\n\nI [attempted to answer it] there and the gist is correct. But I wrote it in a hurry so the\nexample and the explanation could be better. Capturing it properly here.\n\n---\n\nCall it repository or whatever you want, the name doesn't matter. The point is that your\nbusiness logic should be oblivious to the persistence layer. Doesn't matter if it's [sqlc],\nraw database/sql, or [gorm]. If your service functions call sqlc queries directly, your\ncore logic is coupled to your database code. That makes it harder to test in isolation and\nharder to swap out later.\n\nPut a small interface between your business code and your storage code. The business side\ndefines what it needs, the storage side satisfies it, and they live in separate packages.\n\nSay you're building a service that manages books. Start with the domain type and the storage\ninterface:\n\nThe service depends only on that interface:\n\nRegisterBook doesn't know about SQL, sqlc, or Postgres. It builds a Book, asks the store\nto persist it, and gets an ID back.\n\nThe concrete implementation goes in a separate package. This is where sqlc-generated code\nwould live:\n\nWire it up at startup:\n\nIn tests, swap in a fake that satisfies the same interface:\n\nNow the test reads exactly like production code, minus Postgres:\n\nSame service code, no database needed. The test exercises RegisterBook without touching\nSQL. If the storage layer changes tomorrow, the service and its tests stay the same.\n\nA working example with transactions, tests, and an HTTP server is [on GitHub].\n\nSee also:\n\n- [How do you handle transactions with the repository pattern?]\n- [Repositories, transactions, and unit of work in Go]\n\n\n\n\n[r/golang]:\n    https://www.reddit.com/r/golang/\n\n[attempted to answer it]:\n    https://www.reddit.com/r/golang/comments/1rv65k9/comment/oasp30r/\n\n[sqlc]:\n    https://github.com/sqlc-dev/sqlc\n\n[gorm]:\n    https://github.com/go-gorm/gorm\n\n[on GitHub]:\n    https://github.com/rednafi/examples/tree/main/repository-transactions\n\n[How do you handle transactions with the repository pattern?]:\n    /shards/2026/03/transactions-with-repository-pattern/\n\n[Repositories, transactions, and unit of work in Go]:\n    /go/repo-txn-uow/",
  "title": "Do you need a repository layer on top of sqlc?"
}