[{"data":1,"prerenderedAt":1434},["ShallowReactive",2],{"navigation_docs_en":3,"-en-dbx-overview":441,"-en-dbx-overview-surround":1429},[4,45,60,81,112,129,146,173,197,213,242,279,356,372,384,403,429],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"queue","i-lucide-layers","\u002Fen\u002Fqueue","en\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Overview","\u002Fen\u002Fqueue\u002Foverview","en\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F11.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F12.auth\u002F5.social-standalone","i-lucide-log-in",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fen\u002Fstorage\u002Foverview","en\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"Kit","i-lucide-box","\u002Fen\u002Fkit","en\u002F3.kit",[248,251,256,261,266,270,275],{"title":52,"path":249,"stem":250,"icon":244},"\u002Fen\u002Fkit\u002Foverview","en\u002F3.kit\u002F1.overview",{"title":252,"path":253,"stem":254,"icon":255},"Application lifecycle","\u002Fen\u002Fkit\u002Fapp","en\u002F3.kit\u002F2.app","i-lucide-power",{"title":257,"path":258,"stem":259,"icon":260},"Server","\u002Fen\u002Fkit\u002Fserver","en\u002F3.kit\u002F3.server","i-lucide-server",{"title":262,"path":263,"stem":264,"icon":265},"Worker","\u002Fen\u002Fkit\u002Fworker","en\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":267,"path":268,"stem":269,"icon":70},"Realtime","\u002Fen\u002Fkit\u002Frealtime","en\u002F3.kit\u002F5.realtime",{"title":271,"path":272,"stem":273,"icon":274},"Migrations","\u002Fen\u002Fkit\u002Fmigrations","en\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":276,"path":277,"stem":278,"icon":111},"Social login","\u002Fen\u002Fkit\u002Fsocial-login","en\u002F3.kit\u002F7.social-login",{"title":280,"icon":281,"path":282,"stem":283,"children":284,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F4.cli",[285,288,293,298,303,308,313,318,323,328,333,337,342,347,351],{"title":52,"path":286,"stem":287,"icon":281},"\u002Fen\u002Fcli\u002Foverview","en\u002F4.cli\u002F1.overview",{"title":289,"path":290,"stem":291,"icon":292},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":294,"path":295,"stem":296,"icon":297},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":299,"path":300,"stem":301,"icon":302},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":304,"path":305,"stem":306,"icon":307},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":309,"path":310,"stem":311,"icon":312},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":314,"path":315,"stem":316,"icon":317},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":319,"path":320,"stem":321,"icon":322},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":324,"path":325,"stem":326,"icon":327},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":329,"path":330,"stem":331,"icon":332},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":334,"path":335,"stem":336,"icon":244},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F4.cli\u002F5.add-core",{"title":338,"path":339,"stem":340,"icon":341},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":343,"path":344,"stem":345,"icon":346},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":348,"path":349,"stem":350,"icon":265},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F4.cli\u002F8.worker-generators",{"title":352,"path":353,"stem":354,"icon":355},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":357,"icon":227,"path":358,"stem":359,"children":360,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F5.errs",[361,364,368],{"title":52,"path":362,"stem":363,"icon":227},"\u002Fen\u002Ferrs\u002Foverview","en\u002F5.errs\u002F1.overview",{"title":365,"path":366,"stem":367},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F5.errs\u002F2.api",{"title":369,"path":370,"stem":371,"icon":227},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F5.errs\u002F3.integration",{"title":373,"icon":231,"path":374,"stem":375,"children":376,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F6.envconf",[377,380],{"title":52,"path":378,"stem":379,"icon":231},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F6.envconf\u002F1.overview",{"title":381,"path":382,"stem":383},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F6.envconf\u002F2.recipes",{"title":385,"icon":386,"path":387,"stem":388,"children":389,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F7.httperr",[390,393,398],{"title":52,"path":391,"stem":392,"icon":386},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F7.httperr\u002F1.overview",{"title":394,"path":395,"stem":396,"icon":397},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":399,"path":400,"stem":401,"icon":402},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":404,"icon":405,"path":406,"stem":407,"children":408,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F8.dbx",[409,412,416,420,425],{"title":52,"path":410,"stem":411,"icon":405},"\u002Fen\u002Fdbx\u002Foverview","en\u002F8.dbx\u002F1.overview",{"title":413,"path":414,"stem":415,"icon":106},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F8.dbx\u002F2.pg",{"title":417,"path":418,"stem":419,"icon":47},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F8.dbx\u002F3.bunx",{"title":421,"path":422,"stem":423,"icon":424},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":426,"path":427,"stem":428,"icon":317},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F8.dbx\u002F5.seed",{"title":430,"icon":55,"path":431,"stem":432,"children":433,"page":44},"paginate","\u002Fen\u002Fpaginate","en\u002F9.paginate",[434,437],{"title":52,"path":435,"stem":436,"icon":55},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F9.paginate\u002F1.overview",{"title":438,"path":439,"stem":440,"icon":19},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F9.paginate\u002F2.cursor",{"id":442,"title":52,"body":443,"description":1422,"extension":1423,"links":1424,"meta":1425,"navigation":1426,"path":410,"seo":1427,"stem":411,"__hash__":1428},"docs_en\u002Fen\u002F8.dbx\u002F1.overview.md",{"type":444,"value":445,"toc":1413},"minimark",[446,470,515,538,543,582,593,693,699,702,707,755,762,890,921,925,929,946,1001,1034,1066,1069,1139,1161,1164,1168,1185,1304,1311,1315,1350,1357,1361,1409],[447,448,449,452,453,456,457,460,461,464,465,469],"p",{},[450,451,404],"code",{}," is a standalone Go module (",[450,454,455],{},"github.com\u002Fgp-system\u002Fdbx","): a database-agnostic contract, not a driver. It defines exactly two things: ",[450,458,459],{},"Config",", which describes a PostgreSQL connection, and the ",[450,462,463],{},"Transactor"," interface services depend on to span multiple repositories in one transaction. ",[466,467,468],"strong",{},"The root package has no database driver dependency of its own",": the actual implementation lives in a subpackage, and you pick one by importing it:",[471,472,473,496],"ul",{},[474,475,476,484,485,488,489,491,492,495],"li",{},[477,478,479],"a",{"href":414},[466,480,481],{},[450,482,483],{},"dbx\u002Fpg",": the pgx-native stack (the default): pool construction, the ",[450,486,487],{},"DBTX"," query executor, and a ",[450,490,463],{}," backed by ",[450,493,494],{},"pgx.Tx",".",[474,497,498,505,506,511,512,495],{},[477,499,500],{"href":418},[466,501,502],{},[450,503,504],{},"dbx\u002Fbunx",": an optional adapter for projects that prefer the ",[477,507,417],{"href":508,"rel":509},"https:\u002F\u002Fbun.uptrace.dev",[510],"nofollow"," query builder, backed by ",[450,513,514],{},"bun.Tx",[447,516,517,518,521,522,525,526,528,529,531,532,534,535,495],{},"Only one is ever linked into a given binary. Your service and repository layers depend on ",[450,519,520],{},"dbx.Transactor"," and ",[450,523,524],{},"dbx.Config",", never on the concrete implementation. That is why a service's code is identical to the letter whether pgx or bun runs underneath. ",[450,527,404],{}," works the same way with or without the kit, in any Go program; the gpsystem kit's ",[450,530,319],{},"\u002F",[450,533,324],{}," generators simply pick one of the two subpackages for you and wire it into the generated ",[450,536,537],{},"main.go",[539,540,542],"h2",{"id":541},"install","Install",[544,545,550],"pre",{"className":546,"code":547,"language":548,"meta":549,"style":549},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com\u002Fgp-system\u002Fdbx@v0.1.0 # the kit itself uses this tag\ngo get github.com\u002Fgp-system\u002Fdbx@latest\n","sh","",[450,551,552,572],{"__ignoreMap":549},[553,554,557,561,565,568],"span",{"class":555,"line":556},"line",1,[553,558,560],{"class":559},"sBMFI","go",[553,562,564],{"class":563},"sfazB"," get",[553,566,567],{"class":563}," github.com\u002Fgp-system\u002Fdbx@v0.1.0",[553,569,571],{"class":570},"sHwdD"," # the kit itself uses this tag\n",[553,573,575,577,579],{"class":555,"line":574},2,[553,576,560],{"class":559},[553,578,564],{"class":563},[553,580,581],{"class":563}," github.com\u002Fgp-system\u002Fdbx@latest\n",[447,583,584,585,587,588,592],{},"Go 1.25+. The root ",[450,586,404],{}," package depends only on ",[477,589,590],{"href":362},[450,591,357],{},"; everything driver-specific lives behind its own import, so the dependency you actually pull in depends on which subpackage you use:",[594,595,596,609],"table",{},[597,598,599],"thead",{},[600,601,602,606],"tr",{},[603,604,605],"th",{},"Import path",[603,607,608],{},"Adds",[610,611,612,630,650,668,680],"tbody",{},[600,613,614,619],{},[615,616,617],"td",{},[450,618,455],{},[615,620,621,623,624,626,627,629],{},[450,622,357],{}," only: ",[450,625,459],{},", ",[450,628,463],{},", no driver",[600,631,632,637],{},[615,633,634],{},[450,635,636],{},"github.com\u002Fgp-system\u002Fdbx\u002Fpg",[615,638,639,640,626,645],{},"+ ",[477,641,644],{"href":642,"rel":643},"https:\u002F\u002Fgithub.com\u002Fjackc\u002Fpgx",[510],"pgx v5",[477,646,649],{"href":647,"rel":648},"https:\u002F\u002Fgithub.com\u002Fexaring\u002Fotelpgx",[510],"otelpgx",[600,651,652,657],{},[615,653,654],{},[450,655,656],{},"github.com\u002Fgp-system\u002Fdbx\u002Fbunx",[615,658,639,659,626,662,626,665],{},[477,660,417],{"href":508,"rel":661},[510],[450,663,664],{},"bun\u002Fdialect\u002Fpgdialect",[450,666,667],{},"bunotel",[600,669,670,675],{},[615,671,672],{},[450,673,674],{},"github.com\u002Fgp-system\u002Fdbx\u002Fseed",[615,676,677,679],{},[450,678,357],{}," only, same as the root package",[600,681,682,687],{},[615,683,684],{},[450,685,686],{},"github.com\u002Fgp-system\u002Fdbx\u002Fseed\u002Fbunx",[615,688,689,690,692],{},"+ bun (via ",[450,691,504],{},")",[447,694,695,696,698],{},"A project that only ever imports ",[450,697,483],{}," never links bun into its binary, and vice versa.",[539,700,459],{"id":701},"config",[447,703,704,706],{},[450,705,524],{}," describes a single PostgreSQL connection. You compose it into the application's config struct under a prefix:",[544,708,711],{"className":709,"code":710,"language":560,"meta":549,"style":549},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type Config struct {\n    DB dbx.Config `envPrefix:\"DB_\"`\n}\n",[450,712,713,728,749],{"__ignoreMap":549},[553,714,715,719,722,725],{"class":555,"line":556},[553,716,718],{"class":717},"sMK4o","type",[553,720,721],{"class":559}," Config",[553,723,724],{"class":717}," struct",[553,726,727],{"class":717}," {\n",[553,729,730,734,736,738,740,743,746],{"class":555,"line":574},[553,731,733],{"class":732},"sTEyZ","    DB ",[553,735,404],{"class":559},[553,737,495],{"class":717},[553,739,459],{"class":559},[553,741,742],{"class":717}," `",[553,744,745],{"class":563},"envPrefix:\"DB_\"",[553,747,748],{"class":717},"`\n",[553,750,752],{"class":555,"line":751},3,[553,753,754],{"class":717},"}\n",[447,756,757,758,761],{},"which maps to the following environment variables (a generated project's ",[450,759,760],{},".env.example"," lists exactly these):",[594,763,764,777],{},[597,765,766],{},[600,767,768,771,774],{},[603,769,770],{},"Env variable",[603,772,773],{},"Field",[603,775,776],{},"Default",[610,778,779,796,813,828,842,856,873],{},[600,780,781,786,791],{},[615,782,783],{},[450,784,785],{},"DB_HOST",[615,787,788],{},[450,789,790],{},"Host",[615,792,793],{},[450,794,795],{},"localhost",[600,797,798,803,808],{},[615,799,800],{},[450,801,802],{},"DB_PORT",[615,804,805],{},[450,806,807],{},"Port",[615,809,810],{},[450,811,812],{},"5432",[600,814,815,820,825],{},[615,816,817],{},[450,818,819],{},"DB_USER",[615,821,822],{},[450,823,824],{},"User",[615,826,827],{},"required",[600,829,830,835,840],{},[615,831,832],{},[450,833,834],{},"DB_PASSWORD",[615,836,837],{},[450,838,839],{},"Password",[615,841,827],{},[600,843,844,849,854],{},[615,845,846],{},[450,847,848],{},"DB_NAME",[615,850,851],{},[450,852,853],{},"Database",[615,855,827],{},[600,857,858,863,868],{},[615,859,860],{},[450,861,862],{},"DB_SSLMODE",[615,864,865],{},[450,866,867],{},"SSLMode",[615,869,870],{},[450,871,872],{},"disable",[600,874,875,880,885],{},[615,876,877],{},[450,878,879],{},"DB_MAX_CONNS",[615,881,882],{},[450,883,884],{},"MaxConns",[615,886,887],{},[450,888,889],{},"10",[447,891,892,893,896,897,900,901,907,908,913,914,916,917,920],{},"The ",[450,894,895],{},"DSN()"," method renders the config as a ",[450,898,899],{},"postgres:\u002F\u002F"," connection URL. It is consumed by ",[477,902,904],{"href":903},"\u002Fen\u002Fdbx\u002Fpg#pool",[450,905,906],{},"pg.NewPool"," and by the generated ",[477,909,910],{"href":272},[450,911,912],{},"cmd\u002Fmigrate"," binary alike. Loading is done by ",[477,915,373],{"href":378},", with ",[450,918,919],{},".env"," support.",[922,923,924],"note",{},"There is no intermediate config file: the env variables load straight into a typed struct, and a missing required value fails at startup, not on the first query.",[539,926,928],{"id":927},"named-connections","Named connections",[447,930,931,932,935,936,939,940,945],{},"A module's default connection, ",[450,933,934],{},"cfg.DB"," composed under ",[450,937,938],{},"DB_*",", covers the common case: one project, one database, one connector. A second, independent connection composes the same way, under its own prefix, loaded with ",[477,941,942],{"href":382},[450,943,944],{},"envconf.LoadPrefixed",":",[544,947,949],{"className":709,"code":948,"language":560,"meta":549,"style":549},"type Config struct {\n    DB          dbx.Config `envPrefix:\"DB_\"`\n    DBAnalytics dbx.Config `envPrefix:\"DB_ANALYTICS_\"`\n}\n",[450,950,951,961,978,996],{"__ignoreMap":549},[553,952,953,955,957,959],{"class":555,"line":556},[553,954,718],{"class":717},[553,956,721],{"class":559},[553,958,724],{"class":717},[553,960,727],{"class":717},[553,962,963,966,968,970,972,974,976],{"class":555,"line":574},[553,964,965],{"class":732},"    DB          ",[553,967,404],{"class":559},[553,969,495],{"class":717},[553,971,459],{"class":559},[553,973,742],{"class":717},[553,975,745],{"class":563},[553,977,748],{"class":717},[553,979,980,983,985,987,989,991,994],{"class":555,"line":751},[553,981,982],{"class":732},"    DBAnalytics ",[553,984,404],{"class":559},[553,986,495],{"class":717},[553,988,459],{"class":559},[553,990,742],{"class":717},[553,992,993],{"class":563},"envPrefix:\"DB_ANALYTICS_\"",[553,995,748],{"class":717},[553,997,999],{"class":555,"line":998},4,[553,1000,754],{"class":717},[447,1002,1003,1004,626,1007,1010,1011,1015,1016,1018,1019,1022,1023,1026,1027,1030,1031,495],{},"which reads ",[450,1005,1006],{},"DB_ANALYTICS_HOST",[450,1008,1009],{},"DB_ANALYTICS_USER",", and so on, entirely independent of the first connection's pool, transaction and error handling. In a generated project the ",[477,1012,1013],{"href":290},[450,1014,289],{}," generator wires this pattern for you: its own ",[450,1017,524],{}," under ",[450,1020,1021],{},"DB_\u003CNAME>_*",", its own pgx pool, and ",[450,1024,1025],{},"\u003CName>DB"," \u002F ",[450,1028,1029],{},"\u003CName>Transactor"," fields on the module's ",[450,1032,1033],{},"Dependencies",[447,1035,1036,1037,1039,1040,1042,1043,1046,1047,1049,1050,1053,1054,1060,1061,1065],{},"The connector (",[450,1038,413],{}," or ",[450,1041,417],{},") is chosen ",[466,1044,1045],{},"per connection",", not per project: a module can mix a pgx-native default with a bun-backed named connection, or the reverse. This follows directly from the ",[450,1048,463],{}," boundary below: ",[450,1051,1052],{},"WithinTransaction"," on one connection never spans another, so there is no cross-connection transaction to keep consistent, and no reason to force every connection onto the same stack. ",[477,1055,1057],{"href":1056},"\u002Fen\u002Fcli\u002Fadd-surface#binding-the-repository-to-a-named-connection",[450,1058,1059],{},"add surface --db"," binds a module's shared repository skeleton to a named connection; ",[477,1062,1063],{"href":272},[450,1064,912],{}," only ever targets the default connection.",[539,1067,463],{"id":1068},"transactor",[544,1070,1072],{"className":709,"code":1071,"language":560,"meta":549,"style":549},"type Transactor interface {\n    WithinTransaction(ctx context.Context, fn func(ctx context.Context) error) error\n}\n",[450,1073,1074,1086,1135],{"__ignoreMap":549},[553,1075,1076,1078,1081,1084],{"class":555,"line":556},[553,1077,718],{"class":717},[553,1079,1080],{"class":559}," Transactor",[553,1082,1083],{"class":717}," interface",[553,1085,727],{"class":717},[553,1087,1088,1092,1095,1099,1102,1104,1107,1110,1113,1116,1118,1120,1122,1124,1126,1130,1132],{"class":555,"line":574},[553,1089,1091],{"class":1090},"s2Zo4","    WithinTransaction",[553,1093,1094],{"class":717},"(",[553,1096,1098],{"class":1097},"sHdIc","ctx",[553,1100,1101],{"class":559}," context",[553,1103,495],{"class":717},[553,1105,1106],{"class":559},"Context",[553,1108,1109],{"class":717},",",[553,1111,1112],{"class":1097}," fn",[553,1114,1115],{"class":717}," func(",[553,1117,1098],{"class":1097},[553,1119,1101],{"class":559},[553,1121,495],{"class":717},[553,1123,1106],{"class":559},[553,1125,692],{"class":717},[553,1127,1129],{"class":1128},"spNyl"," error",[553,1131,692],{"class":717},[553,1133,1134],{"class":1128}," error\n",[553,1136,1137],{"class":555,"line":751},[553,1138,754],{"class":717},[447,1140,1141,1142,1145,1146,1148,1149,1039,1152,1154,1155,1158,1159,495],{},"This is the single interface application code manages transactions through. The transaction is carried by the context, so every database call inside ",[450,1143,1144],{},"fn",", through ",[450,1147,483],{},"'s ",[450,1150,1151],{},"DB",[450,1153,504],{},"'s resolvers, joins it automatically, without the repositories knowing about it. Commit on ",[450,1156,1157],{},"nil",", rollback on error or panic; a nested call joins the outer transaction. The full semantics and the pattern are covered on ",[477,1160,421],{"href":422},[447,1162,1163],{},"The transaction travels in the context, not in a global connection manager.",[539,1165,1167],{"id":1166},"which-one-to-pick-pgx-or-bun","Which one to pick: pgx or bun?",[447,1169,1170,1171,1174,1175,1178,1179,1181,1182,1184],{},"The choice is ",[466,1172,1173],{},"per project and made at generation time"," (",[450,1176,1177],{},"--db pgx|bun",", default ",[450,1180,413],{},") when you use the kit's generators; the manifest records it and every later generator follows it: see ",[477,1183,319],{"href":320},". Used standalone, without the kit, the choice is simply which subpackage you import.",[594,1186,1187,1203],{},[597,1188,1189],{},[600,1190,1191,1193,1198],{},[603,1192],{},[603,1194,1195,1197],{},[450,1196,483],{}," (pgx)",[603,1199,1200,1202],{},[450,1201,504],{}," (bun)",[610,1204,1205,1232,1257,1279,1293],{},[600,1206,1207,1210,1222],{},[615,1208,1209],{},"Writing queries",[615,1211,1212,1213,531,1216,531,1219,692],{},"hand-written SQL (",[450,1214,1215],{},"Exec",[450,1217,1218],{},"Query",[450,1220,1221],{},"QueryRow",[615,1223,1224,1225,626,1228,1231],{},"bun query builder (",[450,1226,1227],{},"NewSelect",[450,1229,1230],{},"NewInsert",", …) + raw SQL escape hatch",[600,1233,1234,1237,1248],{},[615,1235,1236],{},"Returned types",[615,1238,1239,626,1242,626,1245],{},[450,1240,1241],{},"pgconn.CommandTag",[450,1243,1244],{},"pgx.Rows",[450,1246,1247],{},"pgx.Row",[615,1249,1250,1253,1254],{},[450,1251,1252],{},"bun.IDB",", bun models, ",[450,1255,1256],{},"sql.Result",[600,1258,1259,1262,1268],{},[615,1260,1261],{},"sqlc",[615,1263,1264,1265,1267],{},"directly compatible (",[450,1266,487],{}," is identical)",[615,1269,1270,1271,1274,1275,1278],{},"in ",[450,1272,1273],{},"database\u002Fsql"," mode, through the ",[450,1276,1277],{},"Conn"," resolver",[600,1280,1281,1284,1289],{},[615,1282,1283],{},"Transaction carrier",[615,1285,1286,1288],{},[450,1287,494],{}," in the context",[615,1290,1291,1288],{},[450,1292,514],{},[600,1294,1295,1298,1301],{},[615,1296,1297],{},"Good when",[615,1299,1300],{},"you want full control over the SQL, minimal layers",[615,1302,1303],{},"struct-based models and query-builder comfort",[447,1305,1306,1307,1310],{},"Rule of thumb: if you like writing SQL, stay with pgx: fewer layers, fewer surprises. If you want a query builder with struct-based models, bun will feel familiar, but it is ",[477,1308,1309],{"href":418},"not an ActiveRecord\u002FEloquent-style ORM",", and that is worth knowing up front.",[539,1312,1314],{"id":1313},"deliberately-no-orm-abstraction","Deliberately no ORM abstraction",[447,1316,1317,1318,1322,1323,1325,1326,1329,1330,1332,1333,626,1335,1332,1337,1339,1340,1342,1343,1345,1346,1349],{},"The kit's principle applies here too: ",[477,1319,1321],{"href":1320},"\u002Fen\u002Fgetting-started\u002Fintroduction#it-does-not-hide-your-dependencies","centralize, don't abstract",". ",[450,1324,404],{}," does ",[466,1327,1328],{},"not"," define a common query interface over the two stacks. ",[450,1331,483],{}," returns ",[450,1334,1244],{},[450,1336,504],{},[450,1338,1252],{},". The upstream pgx and bun documentation, examples and Stack Overflow answers apply to your project unchanged. The common denominator is deliberately minimal: the connection description (",[450,1341,459],{},") and the transaction boundary (",[450,1344,463],{},"), because those two are what the ",[466,1347,1348],{},"service layer"," needs to depend on.",[447,1351,1352,1353,1356],{},"Schema management follows from this too: there is no schema builder, and ",[477,1354,1355],{"href":272},"migrations"," are plain, embedded SQL files.",[539,1358,1360],{"id":1359},"pages-in-this-section","Pages in this section",[471,1362,1363,1373,1378,1390,1401],{},[474,1364,1365,1367,1368,626,1370,1372],{},[477,1366,413],{"href":414},": the default stack: pool, ",[450,1369,487],{},[450,1371,1151],{},", repositories",[474,1374,1375,1377],{},[477,1376,417],{"href":418},": the optional query builder adapter",[474,1379,1380,1382,1383,1385,1386,1389],{},[477,1381,421],{"href":422},": the ",[450,1384,463],{}," pattern in depth, with the ",[450,1387,1388],{},"PlaceOrder"," example",[474,1391,1392,1394,1395,521,1398],{},[477,1393,426],{"href":427},": idempotent baseline data with ",[450,1396,1397],{},"dbx\u002Fseed",[450,1399,1400],{},"dbx\u002Fseed\u002Fbunx",[474,1402,1403,1405,1406,1408],{},[477,1404,271],{"href":272},": numbered SQL files, embedded, with a project-owned ",[450,1407,912],{}," binary",[1410,1411,1412],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":549,"searchDepth":574,"depth":574,"links":1414},[1415,1416,1417,1418,1419,1420,1421],{"id":541,"depth":574,"text":542},{"id":701,"depth":574,"text":459},{"id":927,"depth":574,"text":928},{"id":1068,"depth":574,"text":463},{"id":1166,"depth":574,"text":1167},{"id":1313,"depth":574,"text":1314},{"id":1359,"depth":574,"text":1360},"The dbx module, the database-agnostic contract your code depends on, and the two implementations you choose by import.","md",null,{},{"icon":405},{"title":52,"description":1422},"UkPuA_yTiG7CdhOAKAY_fS2f9_ZgGfvplMAZkr50JTs",[1430,1432],{"title":399,"path":400,"stem":401,"description":1431,"icon":402,"children":-1},"Struct-tag-based request validation with go-playground\u002Fvalidator, run as strict middleware, with 422 problem responses.",{"title":413,"path":414,"stem":415,"description":1433,"icon":106,"children":-1},"The pgx-native database stack: the pool, the DBTX query surface and the context-aware DB executor.",1785445890752]