[{"data":1,"prerenderedAt":1157},["ShallowReactive",2],{"navigation_docs_en":3,"-en-http-server":342,"-en-http-server-surround":1152},[4,45,61,96,132,166,196,217,241,265],{"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},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F10.reference",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F10.reference\u002F1.configuration","i-lucide-settings",{"title":57,"path":58,"stem":59,"icon":60},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F10.reference\u002F2.dependencies","i-lucide-package",{"title":62,"icon":63,"path":64,"stem":65,"children":66,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F2.concepts",[67,72,77,82,86,91],{"title":68,"path":69,"stem":70,"icon":71},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F2.concepts\u002F1.architecture","i-lucide-layers",{"title":73,"path":74,"stem":75,"icon":76},"Application lifecycle","\u002Fen\u002Fconcepts\u002Fapplication-lifecycle","en\u002F2.concepts\u002F2.application-lifecycle","i-lucide-power",{"title":78,"path":79,"stem":80,"icon":81},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F2.concepts\u002F3.error-model","i-lucide-shield-alert",{"title":52,"path":83,"stem":84,"icon":85},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F2.concepts\u002F4.configuration","i-lucide-settings-2",{"title":87,"path":88,"stem":89,"icon":90},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F2.concepts\u002F5.codegen-pipeline","i-lucide-file-json",{"title":92,"path":93,"stem":94,"icon":95},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F2.concepts\u002F6.design-patterns","i-lucide-puzzle",{"title":97,"icon":98,"path":99,"stem":100,"children":101,"page":44},"HTTP & Routing","i-lucide-globe","\u002Fen\u002Fhttp","en\u002F3.http",[102,107,112,117,122,127],{"title":103,"path":104,"stem":105,"icon":106},"The server core","\u002Fen\u002Fhttp\u002Fserver","en\u002F3.http\u002F1.server","i-lucide-server",{"title":108,"path":109,"stem":110,"icon":111},"The Fiber engine","\u002Fen\u002Fhttp\u002Ffiber","en\u002F3.http\u002F2.fiber","i-lucide-zap",{"title":113,"path":114,"stem":115,"icon":116},"The chi engine","\u002Fen\u002Fhttp\u002Fchi","en\u002F3.http\u002F3.chi","i-lucide-route",{"title":118,"path":119,"stem":120,"icon":121},"Error responses","\u002Fen\u002Fhttp\u002Ferror-responses","en\u002F3.http\u002F4.error-responses","i-lucide-octagon-alert",{"title":123,"path":124,"stem":125,"icon":126},"Validation","\u002Fen\u002Fhttp\u002Fvalidation","en\u002F3.http\u002F5.validation","i-lucide-badge-check",{"title":128,"path":129,"stem":130,"icon":131},"Pagination","\u002Fen\u002Fhttp\u002Fpagination","en\u002F3.http\u002F6.pagination","i-lucide-list-ordered",{"title":133,"icon":134,"path":135,"stem":136,"children":137,"page":44},"Database","i-lucide-database","\u002Fen\u002Fdatabase","en\u002F4.database",[138,142,147,151,156,161],{"title":139,"path":140,"stem":141,"icon":134},"Overview","\u002Fen\u002Fdatabase\u002Foverview","en\u002F4.database\u002F1.overview",{"title":143,"path":144,"stem":145,"icon":146},"pgx","\u002Fen\u002Fdatabase\u002Fpgx","en\u002F4.database\u002F2.pgx","i-lucide-plug",{"title":148,"path":149,"stem":150,"icon":71},"bun","\u002Fen\u002Fdatabase\u002Fbun","en\u002F4.database\u002F3.bun",{"title":152,"path":153,"stem":154,"icon":155},"Transactions","\u002Fen\u002Fdatabase\u002Ftransactions","en\u002F4.database\u002F4.transactions","i-lucide-git-merge",{"title":157,"path":158,"stem":159,"icon":160},"Migrations","\u002Fen\u002Fdatabase\u002Fmigrations","en\u002F4.database\u002F5.migrations","i-lucide-file-stack",{"title":162,"path":163,"stem":164,"icon":165},"Seeders","\u002Fen\u002Fdatabase\u002Fseeding","en\u002F4.database\u002F6.seeding","i-lucide-sprout",{"title":167,"icon":168,"path":169,"stem":170,"children":171,"page":44},"Async & Background","i-lucide-workflow","\u002Fen\u002Fasync","en\u002F5.async",[172,176,181,186,191],{"title":173,"path":174,"stem":175,"icon":131},"Queue","\u002Fen\u002Fasync\u002Fqueue","en\u002F5.async\u002F1.queue",{"title":177,"path":178,"stem":179,"icon":180},"Events","\u002Fen\u002Fasync\u002Fevents","en\u002F5.async\u002F2.events","i-lucide-radio",{"title":182,"path":183,"stem":184,"icon":185},"Outbox","\u002Fen\u002Fasync\u002Foutbox","en\u002F5.async\u002F3.outbox","i-lucide-inbox",{"title":187,"path":188,"stem":189,"icon":190},"Scheduling","\u002Fen\u002Fasync\u002Fscheduler","en\u002F5.async\u002F4.scheduler","i-lucide-calendar-clock",{"title":192,"path":193,"stem":194,"icon":195},"Worker","\u002Fen\u002Fasync\u002Fworker","en\u002F5.async\u002F5.worker","i-lucide-cog",{"title":197,"icon":198,"path":199,"stem":200,"children":201,"page":44},"Security","i-lucide-shield-check","\u002Fen\u002Fsecurity","en\u002F6.security",[202,207,212],{"title":203,"path":204,"stem":205,"icon":206},"Authentication","\u002Fen\u002Fsecurity\u002Fauthentication","en\u002F6.security\u002F1.authentication","i-lucide-key-round",{"title":208,"path":209,"stem":210,"icon":211},"RBAC","\u002Fen\u002Fsecurity\u002Frbac","en\u002F6.security\u002F2.rbac","i-lucide-users",{"title":213,"path":214,"stem":215,"icon":216},"Policies","\u002Fen\u002Fsecurity\u002Fpolicies","en\u002F6.security\u002F3.policies","i-lucide-gavel",{"title":218,"icon":219,"path":220,"stem":221,"children":222,"page":44},"Observability","i-lucide-activity","\u002Fen\u002Fobservability","en\u002F7.observability",[223,226,231,236],{"title":139,"path":224,"stem":225,"icon":219},"\u002Fen\u002Fobservability\u002Foverview","en\u002F7.observability\u002F1.overview",{"title":227,"path":228,"stem":229,"icon":230},"Logging","\u002Fen\u002Fobservability\u002Flogging","en\u002F7.observability\u002F2.logging","i-lucide-scroll-text",{"title":232,"path":233,"stem":234,"icon":235},"OpenTelemetry","\u002Fen\u002Fobservability\u002Fopentelemetry","en\u002F7.observability\u002F3.opentelemetry","i-lucide-radar",{"title":237,"path":238,"stem":239,"icon":240},"Sentry","\u002Fen\u002Fobservability\u002Fsentry","en\u002F7.observability\u002F4.sentry","i-lucide-bug",{"title":242,"icon":243,"path":244,"stem":245,"children":246,"page":44},"Storage & Mail","i-lucide-hard-drive","\u002Fen\u002Fstorage-mail","en\u002F8.storage-mail",[247,251,256,261],{"title":248,"path":249,"stem":250,"icon":243},"Storage","\u002Fen\u002Fstorage-mail\u002Fstorage","en\u002F8.storage-mail\u002F1.storage",{"title":252,"path":253,"stem":254,"icon":255},"Email","\u002Fen\u002Fstorage-mail\u002Fmail","en\u002F8.storage-mail\u002F2.mail","i-lucide-mail",{"title":257,"path":258,"stem":259,"icon":260},"Notifications","\u002Fen\u002Fstorage-mail\u002Fnotifications","en\u002F8.storage-mail\u002F3.notifications","i-lucide-bell",{"title":262,"path":263,"stem":264,"icon":180},"Realtime","\u002Fen\u002Fstorage-mail\u002Frealtime","en\u002F8.storage-mail\u002F4.realtime",{"title":266,"icon":267,"path":268,"stem":269,"children":270,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F9.cli",[271,274,279,284,289,294,299,303,308,313,318,323,328,333,337],{"title":139,"path":272,"stem":273,"icon":267},"\u002Fen\u002Fcli\u002Foverview","en\u002F9.cli\u002F1.overview",{"title":275,"path":276,"stem":277,"icon":278},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F9.cli\u002F10.add-db","i-lucide-database-zap",{"title":280,"path":281,"stem":282,"icon":283},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F9.cli\u002F11.add-compose","i-lucide-container",{"title":285,"path":286,"stem":287,"icon":288},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F9.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":290,"path":291,"stem":292,"icon":293},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F9.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":295,"path":296,"stem":297,"icon":298},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F9.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":300,"path":301,"stem":302,"icon":165},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F9.cli\u002F15.add-seeder",{"title":304,"path":305,"stem":306,"icon":307},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F9.cli\u002F2.new-project","i-lucide-folder-plus",{"title":309,"path":310,"stem":311,"icon":312},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F9.cli\u002F3.new-module","i-lucide-blocks",{"title":314,"path":315,"stem":316,"icon":317},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F9.cli\u002F4.add-surface","i-lucide-layers-2",{"title":319,"path":320,"stem":321,"icon":322},"add core","\u002Fen\u002Fcli\u002Fadd-core","en\u002F9.cli\u002F5.add-core","i-lucide-box",{"title":324,"path":325,"stem":326,"icon":327},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F9.cli\u002F6.add-handler","i-lucide-webhook",{"title":329,"path":330,"stem":331,"icon":332},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F9.cli\u002F7.new-migration","i-lucide-file-plus",{"title":334,"path":335,"stem":336,"icon":195},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F9.cli\u002F8.worker-generators",{"title":338,"path":339,"stem":340,"icon":341},"upgrade templates","\u002Fen\u002Fcli\u002Fupgrade-templates","en\u002F9.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"id":343,"title":103,"body":344,"description":1145,"extension":1146,"links":1147,"meta":1148,"navigation":1149,"path":104,"seo":1150,"stem":105,"__hash__":1151},"docs_en\u002Fen\u002F3.http\u002F1.server.md",{"type":345,"value":346,"toc":1135},"minimark",[347,380,409,425,429,441,512,515,752,758,763,766,799,803,865,889,892,928,932,967,971,986,1033,1038,1044,1048,1062,1090,1097,1131],[348,349,350,351,355,356,359,360,364,365,368,369,364,372,375,376,379],"p",{},"The ",[352,353,354],"code",{},"server"," package is the engine-neutral core of the HTTP layer: a single ",[352,357,358],{},"Config"," struct consumed identically by both engines, ",[361,362,363],"a",{"href":109},"Fiber"," (",[352,366,367],{},"server\u002Ffiberx",") and ",[361,370,371],{"href":114},"chi",[352,373,374],{},"server\u002Fchix","). It has no HTTP-framework dependency; application code never uses it directly: it picks one of the engines and embeds ",[352,377,378],{},"server.Config"," into its own config struct.",[381,382,387],"pre",{"className":383,"code":384,"language":385,"meta":386,"style":386},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import \"github.com\u002Fgp-system\u002Fgpsystem\u002Fserver\"\n","go","",[352,388,389],{"__ignoreMap":386},[390,391,394,398,402,406],"span",{"class":392,"line":393},"line",1,[390,395,397],{"class":396},"s7zQu","import",[390,399,401],{"class":400},"sMK4o"," \"",[390,403,405],{"class":404},"sBMFI","github.com\u002Fgp-system\u002Fgpsystem\u002Fserver",[390,407,408],{"class":400},"\"\n",[348,410,411,412,416,417,420,421,424],{},"This split is what makes the engine choice a free one: config, environment variables, error rendering and lifecycle are ",[413,414,415],"strong",{},"identical"," across the two engines. What differs is the engine's native API (",[352,418,419],{},"*fiber.App"," vs ",[352,422,423],{},"chi.Router","). Operationally, a project written on Fiber behaves exactly like one on chi.",[426,427,358],"h2",{"id":428},"config",[348,430,431,432,434,435,440],{},"In a generated project, ",[352,433,378],{}," is embedded without a prefix in the application config and loaded from environment variables by ",[361,436,437],{"href":83},[352,438,439],{},"envconf.MustLoad",":",[381,442,445],{"className":383,"code":443,"filename":444,"language":385,"meta":386,"style":386},"type Config struct {\n    Server server.Config\n    DB     dbx.Config `envPrefix:\"DB_\"`\n    \u002F\u002F ...\n}\n","internal\u002Fplatform\u002Fconfig\u002Fconfig.go",[352,446,447,461,476,499,506],{"__ignoreMap":386},[390,448,449,452,455,458],{"class":392,"line":393},[390,450,451],{"class":400},"type",[390,453,454],{"class":404}," Config",[390,456,457],{"class":400}," struct",[390,459,460],{"class":400}," {\n",[390,462,464,468,470,473],{"class":392,"line":463},2,[390,465,467],{"class":466},"sTEyZ","    Server ",[390,469,354],{"class":404},[390,471,472],{"class":400},".",[390,474,475],{"class":404},"Config\n",[390,477,479,482,485,487,489,492,496],{"class":392,"line":478},3,[390,480,481],{"class":466},"    DB     ",[390,483,484],{"class":404},"dbx",[390,486,472],{"class":400},[390,488,358],{"class":404},[390,490,491],{"class":400}," `",[390,493,495],{"class":494},"sfazB","envPrefix:\"DB_\"",[390,497,498],{"class":400},"`\n",[390,500,502],{"class":392,"line":501},4,[390,503,505],{"class":504},"sHwdD","    \u002F\u002F ...\n",[390,507,509],{"class":392,"line":508},5,[390,510,511],{"class":400},"}\n",[348,513,514],{},"The fields and their environment variables:",[516,517,518,537],"table",{},[519,520,521],"thead",{},[522,523,524,528,531,534],"tr",{},[525,526,527],"th",{},"Field",[525,529,530],{},"Env",[525,532,533],{},"Default",[525,535,536],{},"What it controls",[538,539,540,561,588,608,628,649,669,689,710,730],"tbody",{},[522,541,542,548,553,558],{},[543,544,545],"td",{},[352,546,547],{},"ListenAddr",[543,549,550],{},[352,551,552],{},"LISTEN_ADDR",[543,554,555],{},[352,556,557],{},":3000",[543,559,560],{},"the address the engine listens on",[522,562,563,568,573,578],{},[543,564,565],{},[352,566,567],{},"ShutdownTimeout",[543,569,570],{},[352,571,572],{},"SHUTDOWN_TIMEOUT",[543,574,575],{},[352,576,577],{},"10s",[543,579,580,581,584,585],{},"how long in-flight requests get after ",[352,582,583],{},"SIGINT","\u002F",[352,586,587],{},"SIGTERM",[522,589,590,595,600,605],{},[543,591,592],{},[352,593,594],{},"ReadHeaderTimeout",[543,596,597],{},[352,598,599],{},"READ_HEADER_TIMEOUT",[543,601,602],{},[352,603,604],{},"5s",[543,606,607],{},"how long a client may take to send request headers (net\u002Fhttp only, see below)",[522,609,610,615,620,625],{},[543,611,612],{},[352,613,614],{},"ReadTimeout",[543,616,617],{},[352,618,619],{},"READ_TIMEOUT",[543,621,622],{},[352,623,624],{},"30s",[543,626,627],{},"budget for reading the whole request (headers + body)",[522,629,630,635,640,646],{},[543,631,632],{},[352,633,634],{},"WriteTimeout",[543,636,637],{},[352,638,639],{},"WRITE_TIMEOUT",[543,641,642,645],{},[352,643,644],{},"0s"," (disabled)",[543,647,648],{},"budget for writing the response",[522,650,651,656,661,666],{},[543,652,653],{},[352,654,655],{},"IdleTimeout",[543,657,658],{},[352,659,660],{},"IDLE_TIMEOUT",[543,662,663],{},[352,664,665],{},"120s",[543,667,668],{},"how long an idle keep-alive connection stays open",[522,670,671,676,681,686],{},[543,672,673],{},[352,674,675],{},"CORSOrigins",[543,677,678],{},[352,679,680],{},"CORS_ORIGINS",[543,682,683],{},[352,684,685],{},"*",[543,687,688],{},"allowed origins, comma-separated",[522,690,691,696,701,707],{},[543,692,693],{},[352,694,695],{},"BodyLimit",[543,697,698],{},[352,699,700],{},"BODY_LIMIT",[543,702,703,706],{},[352,704,705],{},"4194304"," (4 MiB)",[543,708,709],{},"max request body size in bytes",[522,711,712,717,722,727],{},[543,713,714],{},[352,715,716],{},"ExposeInternalErrors",[543,718,719],{},[352,720,721],{},"HTTP_EXPOSE_INTERNAL_ERRORS",[543,723,724],{},[352,725,726],{},"false",[543,728,729],{},"internal error details in 5xx responses (dev only!)",[522,731,732,737,743,746],{},[543,733,734],{},[352,735,736],{},"Telemetry",[543,738,739],{},[740,741,742],"em",{},"(embedded)",[543,744,745],{},"none",[543,747,748,751],{},[352,749,750],{},"telemetry.Config"," (OTel, logger, Sentry)",[348,753,754,755,472],{},"The full env reference (including the DB, worker and telemetry variables): ",[361,756,757],{"href":53},"Configuration reference",[759,760,762],"h3",{"id":761},"timeouts","Timeouts",[348,764,765],{},"The defaults are tuned for production traffic, not demos:",[767,768,769,779,788],"ul",{},[770,771,772,776,777,472],"li",{},[413,773,774],{},[352,775,594],{}," is the first line of Slowloris defense: a client that drips headers byte by byte gets disconnected after 5 seconds. Only the net\u002Fhttp chassis (chi) uses it as a separate field; fasthttp underneath Fiber folds it into ",[352,778,614],{},[770,780,781,785,786,472],{},[413,782,783],{},[352,784,614],{}," covers reading the whole request. On Fiber it additionally closes idle keep-alive connections on graceful shutdown: with a zero value, shutdown would block for the full ",[352,787,567],{},[770,789,790,794,795,798],{},[413,791,792],{},[352,793,634],{}," is deliberately ",[352,796,797],{},"0"," (disabled): it would also cut off slow or streaming responses (large downloads, SSE). Enable it when all your endpoints are short-lived.",[759,800,802],{"id":801},"body-limit-never-accidentally-disabled","Body limit: never accidentally disabled",[381,804,806],{"className":383,"code":805,"language":385,"meta":386,"style":386},"const DefaultBodyLimit = 4 \u003C\u003C 20 \u002F\u002F 4 MiB\n\nfunc (c Config) EffectiveBodyLimit() int\n",[352,807,808,832,838],{"__ignoreMap":386},[390,809,810,813,816,819,823,826,829],{"class":392,"line":393},[390,811,812],{"class":400},"const",[390,814,815],{"class":466}," DefaultBodyLimit ",[390,817,818],{"class":400},"=",[390,820,822],{"class":821},"sbssI"," 4",[390,824,825],{"class":400}," \u003C\u003C",[390,827,828],{"class":821}," 20",[390,830,831],{"class":504}," \u002F\u002F 4 MiB\n",[390,833,834],{"class":392,"line":463},[390,835,837],{"emptyLinePlaceholder":836},true,"\n",[390,839,840,843,845,849,851,854,858,861],{"class":392,"line":478},[390,841,842],{"class":400},"func",[390,844,364],{"class":400},[390,846,848],{"class":847},"sHdIc","c ",[390,850,358],{"class":404},[390,852,853],{"class":400},")",[390,855,857],{"class":856},"s2Zo4"," EffectiveBodyLimit",[390,859,860],{"class":400},"()",[390,862,864],{"class":863},"spNyl"," int\n",[348,866,867,868,870,871,874,875,877,878,881,882,884,885,888],{},"The engines never read the raw ",[352,869,695],{}," field; they call ",[352,872,873],{},"EffectiveBodyLimit()",": a ",[352,876,797],{}," or negative value does ",[413,879,880],{},"not"," mean \"unlimited\"; it falls back to the 4 MiB default. A typo'd or empty ",[352,883,700],{}," therefore cannot silently remove the cap. Exceeding the limit produces a 413 ",[361,886,887],{"href":119},"problem response"," on both engines.",[759,890,721],{"id":891},"http_expose_internal_errors",[348,893,894,895,898,899,902,903,908,909,912,913,916,917,920,921,924,925,927],{},"With ",[352,896,897],{},"true",", 5xx responses carry the underlying error message in ",[352,900,901],{},"detail",", and, when the chain holds an ",[361,904,905],{"href":79},[352,906,907],{},"errs"," error, the response also gains ",[352,910,911],{},"stack"," and ",[352,914,915],{},"chain"," extension members. It is deliberately a ",[413,918,919],{},"separate"," switch from ",[352,922,923],{},"OTEL_DEV_MODE",": turning on dev logging can never accidentally start leaking internals to clients. Keep it ",[352,926,726],{}," in production: details go to the log and Sentry there, not into the response.",[759,929,931],{"id":930},"the-embedded-telemetry-config","The embedded telemetry config",[348,933,350,934,936,937,939,940,943,944,947,948,947,950,947,953,956,957,960,961,964,965,472],{},[352,935,736],{}," field is a ",[352,938,750],{},": settings for the OTel bootstrap, the default ",[352,941,942],{},"slog"," logger and the optional Sentry integration (",[352,945,946],{},"OTEL_SERVICE_NAME",", ",[352,949,923],{},[352,951,952],{},"LOG_LEVEL",[352,954,955],{},"SENTRY_DSN",", ..., all standard names, no prefix). The engine's ",[352,958,959],{},"Run"," calls ",[352,962,963],{},"telemetry.Setup"," from it before anything else starts. Details: ",[361,966,218],{"href":224},[426,968,970],{"id":969},"the-shared-lifecycle","The shared lifecycle",[348,972,973,974,977,978,981,982,985],{},"The engines do not implement graceful shutdown themselves: both delegate to the engine-agnostic ",[352,975,976],{},"app"," package. The flow is the same in every gpsystem process (HTTP server ",[413,979,980],{},"and"," ",[361,983,984],{"href":193},"worker","):",[987,988,989,994,1001,1004,1019,1030],"ol",{},[770,990,991,993],{},[352,992,963],{},": OTel, logger, Sentry.",[770,995,996,997,1000],{},"Route registration (your ",[352,998,999],{},"register"," function).",[770,1002,1003],{},"Listen: the process blocks from here.",[770,1005,1006,1007,584,1009,1011,1012,1014,1015,1018],{},"On ",[352,1008,583],{},[352,1010,587],{},": the engine stops accepting requests and drains in-flight ones within ",[352,1013,567],{},". A ",[413,1016,1017],{},"second"," signal kills the process immediately.",[770,1020,1021,1022,1025,1026,1029],{},"Cleanups registered with ",[352,1023,1024],{},"WithCloser"," run in ",[413,1027,1028],{},"LIFO"," order (with their own grace period, even when the drain consumed the budget).",[770,1031,1032],{},"Telemetry flushes last: spans emitted by closers still get exported.",[348,1034,1035,1036,472],{},"The exact ordering, signal-handling details and the worker-side counterpart are described on ",[361,1037,73],{"href":74},[1039,1040,1041,1043],"note",{},[352,1042,378],{}," carries the full web-server configuration: every field is loaded from an environment variable, typed, and graceful shutdown is the binary's job, not an external process manager's.",[426,1045,1047],{"id":1046},"choose-your-engine","Choose your engine",[348,1049,1050,1051,364,1054,1057,1058,1061],{},"The two engines are equal peers: you choose at ",[361,1052,1053],{"href":305},"project creation",[352,1055,1056],{},"--engine fiber"," is the default, ",[352,1059,1060],{},"--engine chi"," the alternative), and the generators follow that choice throughout:",[767,1063,1064,1073],{},[770,1065,1066,364,1070,1072],{},[413,1067,1068],{},[361,1069,363],{"href":109},[352,1071,367],{},"): Fiber v3 on top of fasthttp, with a central error handler, bind-time validation, and an expressive router API.",[770,1074,1075,364,1079,1081,1082,1085,1086,1089],{},[413,1076,1077],{},[361,1078,371],{"href":114},[352,1080,374],{},"): thin routing over the standard ",[352,1083,1084],{},"net\u002Fhttp",", where every middleware is a plain ",[352,1087,1088],{},"func(http.Handler) http.Handler"," and every handler is stdlib-compatible. Pick this if you want every net\u002Fhttp tool in the Go ecosystem to work unmodified.",[348,1091,1092,1093,1096],{},"Your business code is untouched by the choice: the ",[361,1094,1095],{"href":88},"generated handler interface"," is identical on both engines, and the service and repository layers never see HTTP at all.",[1039,1098,1100,1101,1103,1104,1107,1108,1110,1111,1113,1114,584,1117,1120,1121,584,1124,1127,1128,1130],{"title":1099},"Projects generated before the server → fiberx\u002Fchix split","Projects generated against the old single ",[352,1102,354],{}," package keep working unchanged. To adopt the new layout, in ",[352,1105,1106],{},"cmd\u002F\u003Cmodule>\u002Fmain.go"," switch the import from ",[352,1109,354],{}," to ",[352,1112,367],{}," and the ",[352,1115,1116],{},"server.Run",[352,1118,1119],{},"server.WithCloser"," calls to ",[352,1122,1123],{},"fiberx.Run",[352,1125,1126],{},"fiberx.WithCloser",". The embedded ",[352,1129,378],{}," stays as is.",[1132,1133,1134],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":386,"searchDepth":463,"depth":463,"links":1136},[1137,1143,1144],{"id":428,"depth":463,"text":358,"children":1138},[1139,1140,1141,1142],{"id":761,"depth":478,"text":762},{"id":801,"depth":478,"text":802},{"id":891,"depth":478,"text":721},{"id":930,"depth":478,"text":931},{"id":969,"depth":463,"text":970},{"id":1046,"depth":463,"text":1047},"The engine-neutral server.Config (timeouts, CORS, body limit) and the shared lifecycle both engines build on.","md",null,{},{"icon":106},{"title":103,"description":1145},"L5Iio2sSwMwPKcY1q6B84ujIgu9zUP33vURh85aUPlU",[1153,1155],{"title":92,"path":93,"stem":94,"description":1154,"icon":95,"children":-1},"A catalog of recurring design patterns in the kit: with code, where to find them, and the canonical external source.",{"title":108,"path":109,"stem":110,"description":1156,"icon":111,"children":-1},"server\u002Ffiberx, a Fiber v3 app with the kit's error handling, validation and telemetry wired in, run with graceful shutdown.",1784668701128]