[{"data":1,"prerenderedAt":1663},["ShallowReactive",2],{"navigation":3,"\u002Fdeployment\u002Fload-testing":413,"\u002Fdeployment\u002Fload-testing-surround":1658},[4,14,36,69,144,384],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fgetting-started","1.getting-started\u002F1.index",[9,10],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":15,"path":16,"stem":17,"children":18,"page":35},"Guides","\u002Fguides","2.guides",[19,23,27,31],{"title":20,"path":21,"stem":22},"Your First Layout","\u002Fguides\u002Fyour-first-layout","2.guides\u002F1.your-first-layout",{"title":24,"path":25,"stem":26},"Your First Page Template","\u002Fguides\u002Fyour-first-page-template","2.guides\u002F2.your-first-page-template",{"title":28,"path":29,"stem":30},"Your First Component","\u002Fguides\u002Fyour-first-component","2.guides\u002F3.your-first-component",{"title":32,"path":33,"stem":34},"Alternative UI Variants","\u002Fguides\u002Falternative-ui-variants","2.guides\u002F4.alternative-ui-variants",false,{"title":37,"path":38,"stem":39,"children":40,"page":35},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[41,45,49,53,57,61,65],{"title":42,"path":43,"stem":44},"How It All Works","\u002Fcore-concepts\u002Farchitecture","3.core-concepts\u002F1.architecture",{"title":46,"path":47,"stem":48},"The Data Model","\u002Fcore-concepts\u002Fthe-data-model","3.core-concepts\u002F2.the-data-model",{"title":50,"path":51,"stem":52},"Layouts & Pages","\u002Fcore-concepts\u002Flayouts-and-pages","3.core-concepts\u002F3.layouts-and-pages",{"title":54,"path":55,"stem":56},"Dynamic Pages","\u002Fcore-concepts\u002Fdynamic-pages","3.core-concepts\u002F4.dynamic-pages",{"title":58,"path":59,"stem":60},"Components","\u002Fcore-concepts\u002Fcomponents","3.core-concepts\u002F5.components",{"title":62,"path":63,"stem":64},"Draft & Publish Workflow","\u002Fcore-concepts\u002Fdraft-and-publish","3.core-concepts\u002F6.draft-and-publish",{"title":66,"path":67,"stem":68},"The Admin Panel","\u002Fcore-concepts\u002Fadmin-panel","3.core-concepts\u002F7.admin-panel",{"title":70,"path":71,"stem":72,"children":73,"page":35},"Api","\u002Fapi","4.api",[74,78,120,124,128,132,136,140],{"title":75,"path":76,"stem":77},"Bundle Setup","\u002Fapi\u002Fbundle-setup","4.api\u002F1.bundle-setup",{"title":58,"path":79,"stem":80,"children":81,"page":35},"\u002Fapi\u002Fcomponents","4.api\u002F2.components",[82,86,107],{"title":83,"path":84,"stem":85},"Creating Components","\u002Fapi\u002Fcomponents\u002Fcreating-components","4.api\u002F2.components\u002F1.creating-components",{"title":87,"path":88,"stem":89,"children":90,"page":35},"Annotations","\u002Fapi\u002Fcomponents\u002Fannotations","4.api\u002F2.components\u002F2.annotations",[91,95,99,103],{"title":92,"path":93,"stem":94},"Publishable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fpublishable","4.api\u002F2.components\u002F2.annotations\u002F1.publishable",{"title":96,"path":97,"stem":98},"Uploadable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fuploadable","4.api\u002F2.components\u002F2.annotations\u002F2.uploadable",{"title":100,"path":101,"stem":102},"Timestamped","\u002Fapi\u002Fcomponents\u002Fannotations\u002Ftimestamped","4.api\u002F2.components\u002F2.annotations\u002F3.timestamped",{"title":104,"path":105,"stem":106},"Explicit Allow Only","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fexplicit-allow-only","4.api\u002F2.components\u002F2.annotations\u002F4.explicit-allow-only",{"title":108,"path":109,"stem":110,"children":111,"page":35},"Built Ins","\u002Fapi\u002Fcomponents\u002Fbuilt-ins","4.api\u002F2.components\u002F3.built-ins",[112,116],{"title":113,"path":114,"stem":115},"Collection Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fcollection-component","4.api\u002F2.components\u002F3.built-ins\u002F1.collection-component",{"title":117,"path":118,"stem":119},"Form Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fform-component","4.api\u002F2.components\u002F3.built-ins\u002F2.form-component",{"title":121,"path":122,"stem":123},"Dynamic & Nested Pages","\u002Fapi\u002Fdynamic-pages","4.api\u002F3.dynamic-pages",{"title":125,"path":126,"stem":127},"Users & Security","\u002Fapi\u002Fusers-and-security","4.api\u002F4.users-and-security",{"title":129,"path":130,"stem":131},"Data Fixtures","\u002Fapi\u002Fdata-fixtures","4.api\u002F5.data-fixtures",{"title":133,"path":134,"stem":135},"Configuration Reference","\u002Fapi\u002Fconfiguration","4.api\u002F6.configuration",{"title":137,"path":138,"stem":139},"Console Commands","\u002Fapi\u002Fconsole-commands","4.api\u002F7.console-commands",{"title":141,"path":142,"stem":143},"Debugging & Profiler","\u002Fapi\u002Fdebugging","4.api\u002F8.debugging",{"title":145,"path":146,"stem":147,"children":148,"page":35},"Nuxt Module","\u002Fnuxt-module","5.nuxt-module",[149,153,157,161,174,194,215,248,332,356,360],{"title":150,"path":151,"stem":152},"Module Setup","\u002Fnuxt-module\u002Fmodule-setup","5.nuxt-module\u002F1.module-setup",{"title":154,"path":155,"stem":156},"PWA & Offline","\u002Fnuxt-module\u002Fpwa","5.nuxt-module\u002F10.pwa",{"title":158,"path":159,"stem":160},"Page Caching","\u002Fnuxt-module\u002Fpage-caching","5.nuxt-module\u002F11.page-caching",{"title":162,"path":163,"stem":164,"children":165,"page":35},"Configuration","\u002Fnuxt-module\u002Fconfiguration","5.nuxt-module\u002F2.configuration",[166,170],{"title":167,"path":168,"stem":169},"Nuxt Config","\u002Fnuxt-module\u002Fconfiguration\u002Fnuxt-config","5.nuxt-module\u002F2.configuration\u002F1.nuxt-config",{"title":171,"path":172,"stem":173},"Site Config & SEO","\u002Fnuxt-module\u002Fconfiguration\u002Fsite-config-and-seo","5.nuxt-module\u002F2.configuration\u002F2.site-config-and-seo",{"title":175,"path":176,"stem":177,"children":178,"page":35},"Building Your Ui","\u002Fnuxt-module\u002Fbuilding-your-ui","5.nuxt-module\u002F3.building-your-ui",[179,183,187,190],{"title":180,"path":181,"stem":182},"Layouts","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-layouts","5.nuxt-module\u002F3.building-your-ui\u002F1.creating-layouts",{"title":184,"path":185,"stem":186},"Page Templates","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-page-templates","5.nuxt-module\u002F3.building-your-ui\u002F2.creating-page-templates",{"title":83,"path":188,"stem":189},"\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-components","5.nuxt-module\u002F3.building-your-ui\u002F3.creating-components",{"title":191,"path":192,"stem":193},"CLI Generator","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcwa-cli","5.nuxt-module\u002F3.building-your-ui\u002F4.cwa-cli",{"title":195,"path":196,"stem":197,"children":198,"page":35},"Cwa Components","\u002Fnuxt-module\u002Fcwa-components","5.nuxt-module\u002F4.cwa-components",[199,203,207,211],{"title":200,"path":201,"stem":202},"\u003CCwaComponentGroup \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-component-group","5.nuxt-module\u002F4.cwa-components\u002F1.cwa-component-group",{"title":204,"path":205,"stem":206},"\u003CCwaPage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-page","5.nuxt-module\u002F4.cwa-components\u002F2.cwa-page",{"title":208,"path":209,"stem":210},"\u003CCwaLink \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-link","5.nuxt-module\u002F4.cwa-components\u002F3.cwa-link",{"title":212,"path":213,"stem":214},"\u003CCwaDefaultLayout \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-default-layout","5.nuxt-module\u002F4.cwa-components\u002F5.cwa-default-layout",{"title":216,"path":217,"stem":218,"children":219,"page":35},"Cwa Api","\u002Fnuxt-module\u002Fcwa-api","5.nuxt-module\u002F5.cwa-api",[220,224,228,232,236,240,244],{"title":221,"path":222,"stem":223},"Overview","\u002Fnuxt-module\u002Fcwa-api\u002Foverview","5.nuxt-module\u002F5.cwa-api\u002F1.overview",{"title":225,"path":226,"stem":227},"Resources","\u002Fnuxt-module\u002Fcwa-api\u002Fresources","5.nuxt-module\u002F5.cwa-api\u002F2.resources",{"title":229,"path":230,"stem":231},"Resources Manager","\u002Fnuxt-module\u002Fcwa-api\u002Fresources-manager","5.nuxt-module\u002F5.cwa-api\u002F3.resources-manager",{"title":233,"path":234,"stem":235},"Auth","\u002Fnuxt-module\u002Fcwa-api\u002Fauth","5.nuxt-module\u002F5.cwa-api\u002F4.auth",{"title":237,"path":238,"stem":239},"Forms","\u002Fnuxt-module\u002Fcwa-api\u002Fforms","5.nuxt-module\u002F5.cwa-api\u002F5.forms",{"title":241,"path":242,"stem":243},"Admin","\u002Fnuxt-module\u002Fcwa-api\u002Fadmin","5.nuxt-module\u002F5.cwa-api\u002F6.admin",{"title":245,"path":246,"stem":247},"Site Config","\u002Fnuxt-module\u002Fcwa-api\u002Fsite-config","5.nuxt-module\u002F5.cwa-api\u002F7.site-config",{"title":249,"path":250,"stem":251,"children":252,"page":35},"Composables","\u002Fnuxt-module\u002Fcomposables","5.nuxt-module\u002F6.composables",[253,261,298,315],{"title":254,"path":255,"stem":256,"children":257,"page":35},"Layout","\u002Fnuxt-module\u002Fcomposables\u002Flayout","5.nuxt-module\u002F6.composables\u002F0.layout",[258],{"title":254,"path":259,"stem":260},"\u002Fnuxt-module\u002Fcomposables\u002Flayout\u002Fuse-cwa-layout","5.nuxt-module\u002F6.composables\u002F0.layout\u002F1.use-cwa-layout",{"title":262,"path":263,"stem":264,"children":265,"page":35},"Component","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent","5.nuxt-module\u002F6.composables\u002F1.component",[266,270,274,278,282,286,290,294],{"title":267,"path":268,"stem":269},"Component (recommended)","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-component","5.nuxt-module\u002F6.composables\u002F1.component\u002F0.use-cwa-component",{"title":271,"path":272,"stem":273},"Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F1.use-cwa-resource",{"title":275,"path":276,"stem":277},"Collection Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-collection-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F2.use-cwa-collection-resource",{"title":279,"path":280,"stem":281},"File Field","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-file-field","5.nuxt-module\u002F6.composables\u002F1.component\u002F3.use-cwa-file-field",{"title":283,"path":284,"stem":285},"Form","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form","5.nuxt-module\u002F6.composables\u002F1.component\u002F4.use-cwa-form",{"title":287,"path":288,"stem":289},"Form Input","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-input","5.nuxt-module\u002F6.composables\u002F1.component\u002F5.use-cwa-form-input",{"title":291,"path":292,"stem":293},"Form Repeated","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-repeated","5.nuxt-module\u002F6.composables\u002F1.component\u002F6.use-cwa-form-repeated",{"title":295,"path":296,"stem":297},"Form Collection","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-collection","5.nuxt-module\u002F6.composables\u002F1.component\u002F7.use-cwa-form-collection",{"title":299,"path":300,"stem":301,"children":302,"page":35},"Admin Manager","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager","5.nuxt-module\u002F6.composables\u002F2.admin-manager",[303,307,311],{"title":304,"path":305,"stem":306},"Manager Tab","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-manager-tab","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F1.use-cwa-resource-manager-tab",{"title":308,"path":309,"stem":310},"Resource Model","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-model","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F2.use-cwa-resource-model",{"title":312,"path":313,"stem":314},"Resource Upload","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-upload","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F3.use-cwa-resource-upload",{"title":316,"path":317,"stem":318,"children":319,"page":35},"Utilities","\u002Fnuxt-module\u002Fcomposables\u002Futilities","5.nuxt-module\u002F6.composables\u002F3.utilities",[320,324,328],{"title":321,"path":322,"stem":323},"Resource Endpoint","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-endpoint","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F1.use-cwa-resource-endpoint",{"title":325,"path":326,"stem":327},"Query Model","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-query-bound-model","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F2.use-query-bound-model",{"title":329,"path":330,"stem":331},"Resource Route","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-route","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F3.use-cwa-resource-route",{"title":333,"path":334,"stem":335,"children":336,"page":35},"Component Helpers","\u002Fnuxt-module\u002Fcomponent-helpers","5.nuxt-module\u002F7.component-helpers",[337,341,345,349,353],{"title":338,"path":339,"stem":340},"Images & Media","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fimages-and-uploads","5.nuxt-module\u002F7.component-helpers\u002F1.images-and-uploads",{"title":342,"path":343,"stem":344},"Collections & Pagination","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fcollections-and-pagination","5.nuxt-module\u002F7.component-helpers\u002F2.collections-and-pagination",{"title":346,"path":347,"stem":348},"HTML Content","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fhtml-content","5.nuxt-module\u002F7.component-helpers\u002F3.html-content",{"title":350,"path":351,"stem":352},"Real-Time Updates","\u002Fnuxt-module\u002Fcomponent-helpers\u002Freal-time-updates","5.nuxt-module\u002F7.component-helpers\u002F4.real-time-updates",{"title":237,"path":354,"stem":355},"\u002Fnuxt-module\u002Fcomponent-helpers\u002Fforms","5.nuxt-module\u002F7.component-helpers\u002F5.forms",{"title":357,"path":358,"stem":359},"Authentication","\u002Fnuxt-module\u002Fauthentication","5.nuxt-module\u002F8.authentication",{"title":361,"path":362,"stem":363,"children":364,"page":35},"Cwa Layer","\u002Fnuxt-module\u002Fcwa-layer","5.nuxt-module\u002F9.cwa-layer",[365,368,372,376,380],{"title":221,"path":366,"stem":367},"\u002Fnuxt-module\u002Fcwa-layer\u002Foverview","5.nuxt-module\u002F9.cwa-layer\u002F1.overview",{"title":369,"path":370,"stem":371},"Auth Pages","\u002Fnuxt-module\u002Fcwa-layer\u002Fauth-pages","5.nuxt-module\u002F9.cwa-layer\u002F2.auth-pages",{"title":373,"path":374,"stem":375},"Admin Panel","\u002Fnuxt-module\u002Fcwa-layer\u002Fadmin-panel","5.nuxt-module\u002F9.cwa-layer\u002F3.admin-panel",{"title":377,"path":378,"stem":379},"Styling","\u002Fnuxt-module\u002Fcwa-layer\u002Fstyling","5.nuxt-module\u002F9.cwa-layer\u002F4.styling",{"title":381,"path":382,"stem":383},"Date Pickers","\u002Fnuxt-module\u002Fcwa-layer\u002Fdate-pickers","5.nuxt-module\u002F9.cwa-layer\u002F5.date-pickers",{"title":385,"path":386,"stem":387,"children":388,"page":35},"Deployment","\u002Fdeployment","6.deployment",[389,393,397,401,405,409],{"title":390,"path":391,"stem":392},"Docker","\u002Fdeployment\u002Fdocker","6.deployment\u002F1.docker",{"title":394,"path":395,"stem":396},"Kubernetes & Helm","\u002Fdeployment\u002Fkubernetes","6.deployment\u002F2.kubernetes",{"title":398,"path":399,"stem":400},"CI\u002FCD","\u002Fdeployment\u002Fci-cd","6.deployment\u002F3.ci-cd",{"title":402,"path":403,"stem":404},"Load Testing","\u002Fdeployment\u002Fload-testing","6.deployment\u002F4.load-testing",{"title":406,"path":407,"stem":408},"Faster Functional Tests","\u002Fdeployment\u002Ffaster-functional-tests","6.deployment\u002F5.faster-functional-tests",{"title":410,"path":411,"stem":412},"Cloudflare","\u002Fdeployment\u002Fcloudflare","6.deployment\u002F6.cloudflare",{"id":414,"title":402,"badge":415,"body":416,"description":1653,"extension":1654,"links":415,"meta":1655,"navigation":630,"path":403,"seo":1656,"stem":404,"__hash__":1657},"docs\u002F6.deployment\u002F4.load-testing.md",null,{"type":417,"value":418,"toc":1640},"minimark",[419,440,448,453,498,505,557,566,585,589,707,713,729,744,748,847,858,862,868,1174,1180,1186,1222,1237,1300,1330,1335,1338,1400,1415,1419,1422,1430,1521,1535,1561,1565,1576,1611,1615,1636],[420,421,422,423,430,431,435,436,439],"p",{},"The template ships a ",[424,425,429],"a",{"href":426,"rel":427},"https:\u002F\u002Fk6.io",[428],"nofollow","k6"," script at ",[432,433,434],"code",{},"bin\u002Fload-test\u002Flaunch.js",". It tells you how many visitors your site can serve and how quickly. It also tells you whether those visitors got the ",[424,437,438],{"href":159},"page cache"," or a fresh server-side render (SSR), because the two differ by orders of magnitude.",[420,441,442,443,447],{},"It is a manual tool. ",[444,445,446],"strong",{},"It is not part of CI, on purpose."," A load test sends real traffic and costs money on an autoscaled cluster, so someone should decide to run it.",[449,450,452],"h2",{"id":451},"install-k6","Install k6",[454,455,460],"pre",{"className":456,"code":457,"language":458,"meta":459,"style":459},"language-sh shiki shiki-themes github-light github-dark material-theme-palenight","brew install k6                      # macOS\nsudo apt-get install k6              # Debian\u002FUbuntu, after adding Grafana's apt repo\n","sh","",[432,461,462,482],{"__ignoreMap":459},[463,464,467,471,475,478],"span",{"class":465,"line":466},"line",1,[463,468,470],{"class":469},"sRCss","brew",[463,472,474],{"class":473},"sLL54"," install",[463,476,477],{"class":473}," k6",[463,479,481],{"class":480},"sTBSN","                      # macOS\n",[463,483,485,488,491,493,495],{"class":465,"line":484},2,[463,486,487],{"class":469},"sudo",[463,489,490],{"class":473}," apt-get",[463,492,474],{"class":473},[463,494,477],{"class":473},[463,496,497],{"class":480},"              # Debian\u002FUbuntu, after adding Grafana's apt repo\n",[420,499,500,501,504],{},"Or skip the install and use Docker. Pass the variables with ",[432,502,503],{},"-e"," and the script on stdin:",[454,506,508],{"className":456,"code":507,"language":458,"meta":459,"style":459},"docker run --rm -i -e BASE_URL=https:\u002F\u002Fstaging.example.com -e CONFIRM=yes \\\n  grafana\u002Fk6 run - \u003C bin\u002Fload-test\u002Flaunch.js\n",[432,509,510,540],{"__ignoreMap":459},[463,511,512,515,518,522,525,528,531,533,536],{"class":465,"line":466},[463,513,514],{"class":469},"docker",[463,516,517],{"class":473}," run",[463,519,521],{"class":520},"szhYu"," --rm",[463,523,524],{"class":520}," -i",[463,526,527],{"class":520}," -e",[463,529,530],{"class":473}," BASE_URL=https:\u002F\u002Fstaging.example.com",[463,532,527],{"class":520},[463,534,535],{"class":473}," CONFIRM=yes",[463,537,539],{"class":538},"sc2zw"," \\\n",[463,541,542,545,547,550,554],{"class":465,"line":484},[463,543,544],{"class":473},"  grafana\u002Fk6",[463,546,517],{"class":473},[463,548,549],{"class":473}," -",[463,551,553],{"class":552},"sVlFx"," \u003C",[463,555,556],{"class":473}," bin\u002Fload-test\u002Flaunch.js\n",[420,558,559,560,565],{},"See the ",[424,561,564],{"href":562,"rel":563},"https:\u002F\u002Fgrafana.com\u002Fdocs\u002Fk6\u002Flatest\u002Fset-up\u002Finstall-k6\u002F",[428],"k6 install guide"," for other platforms.",[567,568,571],"callout",{"icon":569,"color":570},"i-heroicons-exclamation-triangle","warning",[420,572,573,576,577,580,581,584],{},[444,574,575],{},"Run it from a cloud VM near the cluster, not a laptop."," Use a VM in the same region for anything bigger than ",[432,578,579],{},"smoke",". A laptop runs out of sockets and bandwidth first. At around 300 visitors k6 reports ",[432,582,583],{},"dial: i\u002Fo timeout"," long before the cluster notices anything, and the numbers measure your Wi-Fi. A small VM (2 vCPU) is enough for a few hundred visitors.",[449,586,588],{"id":587},"run-a-test","Run a test",[454,590,592],{"className":456,"code":591,"language":458,"meta":459,"style":459},"# The local stack has a self-signed certificate. Local hosts need no confirmation.\nBASE_URL=https:\u002F\u002Flocalhost INSECURE=true k6 run bin\u002Fload-test\u002Flaunch.js\n\n# Any other host needs CONFIRM=yes.\nBASE_URL=https:\u002F\u002Fstaging.example.com CONFIRM=yes MODE=capacity k6 run bin\u002Fload-test\u002Flaunch.js\nBASE_URL=https:\u002F\u002Fwww.example.com CONFIRM=yes MODE=surge PEOPLE=300 k6 run bin\u002Fload-test\u002Flaunch.js\n",[432,593,594,599,625,632,638,670],{"__ignoreMap":459},[463,595,596],{"class":465,"line":466},[463,597,598],{"class":480},"# The local stack has a self-signed certificate. Local hosts need no confirmation.\n",[463,600,601,605,608,611,614,616,619,621,623],{"class":465,"line":484},[463,602,604],{"class":603},"sPB8G","BASE_URL",[463,606,607],{"class":552},"=",[463,609,610],{"class":473},"https:\u002F\u002Flocalhost",[463,612,613],{"class":603}," INSECURE",[463,615,607],{"class":552},[463,617,618],{"class":473},"true",[463,620,477],{"class":469},[463,622,517],{"class":473},[463,624,556],{"class":473},[463,626,628],{"class":465,"line":627},3,[463,629,631],{"emptyLinePlaceholder":630},true,"\n",[463,633,635],{"class":465,"line":634},4,[463,636,637],{"class":480},"# Any other host needs CONFIRM=yes.\n",[463,639,641,643,645,648,651,653,656,659,661,664,666,668],{"class":465,"line":640},5,[463,642,604],{"class":603},[463,644,607],{"class":552},[463,646,647],{"class":473},"https:\u002F\u002Fstaging.example.com",[463,649,650],{"class":603}," CONFIRM",[463,652,607],{"class":552},[463,654,655],{"class":473},"yes",[463,657,658],{"class":603}," MODE",[463,660,607],{"class":552},[463,662,663],{"class":473},"capacity",[463,665,477],{"class":469},[463,667,517],{"class":473},[463,669,556],{"class":473},[463,671,673,675,677,680,682,684,686,688,690,693,696,698,701,703,705],{"class":465,"line":672},6,[463,674,604],{"class":603},[463,676,607],{"class":552},[463,678,679],{"class":473},"https:\u002F\u002Fwww.example.com",[463,681,650],{"class":603},[463,683,607],{"class":552},[463,685,655],{"class":473},[463,687,658],{"class":603},[463,689,607],{"class":552},[463,691,692],{"class":473},"surge",[463,694,695],{"class":603}," PEOPLE",[463,697,607],{"class":552},[463,699,700],{"class":473},"300",[463,702,477],{"class":469},[463,704,517],{"class":473},[463,706,556],{"class":473},[420,708,709,710,712],{},"Start with ",[432,711,579],{},". It checks the script, the target and the cache headers before you point real load at anything.",[420,714,715,716,719,720,724,725,728],{},"By default the pages come from ",[432,717,718],{},"\u002Fsitemap.xml",", read the same way as the ",[424,721,723],{"href":722},"\u002Fdeployment\u002Fci-cd#warming-the-cache-after-a-deploy","cache warm after a deploy",". Set ",[432,726,727],{},"PAGES=\u002F,\u002Fabout"," to test specific paths instead.",[567,730,732],{"icon":731},"i-heroicons-photo",[420,733,734,737,738,740,741,743],{},[444,735,736],{},"Image placeholder:"," a terminal showing a ",[432,739,579],{}," run against ",[432,742,610],{},", from the start banner to the summary.",[449,745,747],{"id":746},"modes","Modes",[749,750,751,769],"table",{},[752,753,754],"thead",{},[755,756,757,763,766],"tr",{},[758,759,760],"th",{},[432,761,762],{},"MODE",[758,764,765],{},"What it does",[758,767,768],{},"Use it to",[770,771,772,790,810,829],"tbody",{},[755,773,774,780,787],{},[775,776,777,779],"td",{},[432,778,579],{}," (default)",[775,781,782,783,786],{},"2 visitors for 30s (",[432,784,785],{},"DURATION",")",[775,788,789],{},"Check everything is wired up before a bigger test.",[755,791,792,796,807],{},[775,793,794],{},[432,795,663],{},[775,797,798,799,802,803,806],{},"Steps the arrival rate up to ",[432,800,801],{},"PEAK_RATE"," visitors per second, ",[432,804,805],{},"STAGE"," (30s) per step, then holds.",[775,808,809],{},"Find the point where latency runs away. Size your pods against this.",[755,811,812,816,826],{},[775,813,814],{},[432,815,692],{},[775,817,818,819,822,823,825],{},"Ramps to ",[432,820,821],{},"PEOPLE"," visitors over 60s, holds for 3m (",[432,824,785],{},"), then ramps down.",[775,827,828],{},"Test a launch moment: a URL on a screen and a room reaching for their phones.",[755,830,831,836,844],{},[775,832,833],{},[432,834,835],{},"soak",[775,837,838,841,842,786],{},[432,839,840],{},"PEOPLE \u002F 6"," visitors for 15m (",[432,843,785],{},[775,845,846],{},"Catch leaks and slow degradation under steady traffic.",[420,848,849,850,853,854,857],{},"Each visitor loads a page and its ",[432,851,852],{},"\u002F_nuxt"," files, then reads for 2–6 seconds. Next it makes one client-side navigation, which in CWA is two ",[432,855,856],{},"\u002F_api"," calls (the route and its resource manifest), not another server render. Then it reads for 3–9 seconds more.",[449,859,861],{"id":860},"environment-variables","Environment variables",[420,863,864,865,867],{},"Only ",[432,866,604],{}," is required.",[749,869,870,883],{},[752,871,872],{},[755,873,874,877,880],{},[758,875,876],{},"Variable",[758,878,879],{},"Default",[758,881,882],{},"Meaning",[770,884,885,900,915,937,963,986,1004,1024,1037,1052,1070,1099,1115,1133,1148,1162],{},[755,886,887,891,894],{},[775,888,889],{},[432,890,604],{},[775,892,893],{},"(required)",[775,895,896,897,899],{},"Site origin, such as ",[432,898,679],{},".",[755,901,902,907,909],{},[775,903,904],{},[432,905,906],{},"CONFIRM",[775,908],{},[775,910,911,912,914],{},"Must be ",[432,913,655],{}," for any host that is not local.",[755,916,917,921,925],{},[775,918,919],{},[432,920,762],{},[775,922,923],{},[432,924,579],{},[775,926,927,929,930,929,932,934,935,899],{},[432,928,579],{},", ",[432,931,663],{},[432,933,692],{}," or ",[432,936,835],{},[755,938,939,943,948],{},[775,940,941],{},[432,942,821],{},[775,944,945],{},[432,946,947],{},"100",[775,949,950,951,953,954,956,957,959,960,962],{},"Simultaneous visitors for ",[432,952,692],{},". ",[432,955,835],{}," uses a sixth of it, and ",[432,958,663],{}," derives ",[432,961,801],{}," from it.",[755,964,965,970,975],{},[775,966,967],{},[432,968,969],{},"CACHE",[775,971,972],{},[432,973,974],{},"warm",[775,976,977,929,979,934,982,985],{},[432,978,974],{},[432,980,981],{},"cold",[432,983,984],{},"mixed",". See below.",[755,987,988,993,998],{},[775,989,990],{},[432,991,992],{},"COLD_RATIO",[775,994,995],{},[432,996,997],{},"0.2",[775,999,1000,1001,899],{},"Share of page loads that bust the cache when ",[432,1002,1003],{},"CACHE=mixed",[755,1005,1006,1011,1016],{},[775,1007,1008],{},[432,1009,1010],{},"COLD_API",[775,1012,1013],{},[432,1014,1015],{},"false",[775,1017,1018,1020,1021,1023],{},[432,1019,618],{}," also busts the cache on the ",[432,1022,856],{}," calls in cold and mixed loads.",[755,1025,1026,1031,1034],{},[775,1027,1028],{},[432,1029,1030],{},"PAGES",[775,1032,1033],{},"the sitemap",[775,1035,1036],{},"Comma-separated paths to test instead of the sitemap.",[755,1038,1039,1044,1049],{},[775,1040,1041],{},[432,1042,1043],{},"MAX_PAGES",[775,1045,1046],{},[432,1047,1048],{},"50",[775,1050,1051],{},"Most pages taken from the sitemap.",[755,1053,1054,1059,1064],{},[775,1055,1056],{},[432,1057,1058],{},"MAX_ASSETS",[775,1060,1061],{},[432,1062,1063],{},"12",[775,1065,1066,1067,1069],{},"Most ",[432,1068,852],{}," files fetched per page load.",[755,1071,1072,1076,1088],{},[775,1073,1074],{},[432,1075,785],{},[775,1077,1078,1081,1082,1081,1085],{},[432,1079,1080],{},"30s"," \u002F ",[432,1083,1084],{},"3m",[432,1086,1087],{},"15m",[775,1089,1090,1091,1093,1094,1096,1097,899],{},"Length of ",[432,1092,579],{},", of the ",[432,1095,692],{}," hold, or of ",[432,1098,835],{},[755,1100,1101,1105,1109],{},[775,1102,1103],{},[432,1104,805],{},[775,1106,1107],{},[432,1108,1080],{},[775,1110,1111,1112,1114],{},"Length of each ",[432,1113,663],{}," step.",[755,1116,1117,1121,1127],{},[775,1118,1119],{},[432,1120,801],{},[775,1122,1123,1126],{},[432,1124,1125],{},"PEOPLE \u002F 7",", at least 2",[775,1128,1129,1130,1132],{},"The top arrival rate for ",[432,1131,663],{},", in visitors per second.",[755,1134,1135,1140,1145],{},[775,1136,1137],{},[432,1138,1139],{},"PAGE_P95_MS",[775,1141,1142],{},[432,1143,1144],{},"2000",[775,1146,1147],{},"Threshold for the p95 time to first byte of pages.",[755,1149,1150,1155,1157],{},[775,1151,1152],{},[432,1153,1154],{},"INSECURE",[775,1156],{},[775,1158,1159,1161],{},[432,1160,618],{}," skips TLS verification. Use it only for the local self-signed stack.",[755,1163,1164,1169,1171],{},[775,1165,1166],{},[432,1167,1168],{},"SUMMARY_JSON",[775,1170],{},[775,1172,1173],{},"Also write k6's full summary data to this file.",[449,1175,1177,1178],{"id":1176},"cached-or-rendered-cache","Cached or rendered: ",[432,1179,969],{},[420,1181,1182,1183,1185],{},"Page HTML and ",[432,1184,856],{}," responses are served by the Souin cache in front of Nuxt and php. A test that only hits the cache says nothing about SSR, and the reverse is true too. So choose what you are measuring:",[1187,1188,1189,1197,1212],"ul",{},[1190,1191,1192,1196],"li",{},[444,1193,1194],{},[432,1195,974],{}," sends plain anonymous requests, as a visitor does. After the first request for each page, these should be cache hits. This is what your visitors get.",[1190,1198,1199,1203,1204,1207,1208,1211],{},[444,1200,1201],{},[432,1202,981],{}," adds a unique ",[432,1205,1206],{},"k6cb="," value to each page request, to make every one miss the cache and be rendered by Nuxt. This is the cost of SSR, and the worst case after a purge or a deploy. The template's query allowlist now drops ",[432,1209,1210],{},"k6cb"," from pages, though: see below.",[1190,1213,1214,1218,1219,1221],{},[444,1215,1216],{},[432,1217,984],{}," makes ",[432,1220,992],{}," of page loads cold and the rest warm.",[420,1223,1224,1225,1227,1228,953,1231,1233,1234,1236],{},"The navigation's ",[432,1226,856],{}," calls stay cacheable unless you set ",[432,1229,1230],{},"COLD_API=true",[432,1232,856],{}," keeps every query parameter, so ",[432,1235,1010],{}," still busts the cache.",[567,1238,1239,1257,1294],{"icon":569,"color":570},[420,1240,1241,1244,1245,1248,1249,1253,1254,1256],{},[444,1242,1243],{},"A cold run's page requests are cache hits on a current template."," From components-web-app ",[432,1246,1247],{},"4cbe05a",", the Caddyfile's ",[424,1250,1252],{"href":1251},"\u002Fnuxt-module\u002Fpage-caching#query-parameters-on-pages","query allowlist"," drops every page parameter it doesn't list, ",[432,1255,1210],{}," included. A cold run then simulates a cache-busting flood, and the hits show the protection working. To measure real render cost, on a test stack only:",[1187,1258,1259,1273],{},[1190,1260,1261,1262,1264,1265,1268,1269,1272],{},"add ",[432,1263,1210],{}," to ",[432,1266,1267],{},"CACHE_QUERY_ALLOWLIST",", for example ",[432,1270,1271],{},"CACHE_QUERY_ALLOWLIST=\"page search order k6cb\"",", and",[1190,1274,1275,1276,1279,1280,934,1282,1284,1285,1289,1290,1293],{},"set ",[432,1277,1278],{},"RATE_LIMIT_ENABLED=false",". A ",[432,1281,663],{},[432,1283,692],{}," run from one machine sends far more misses than the ",[424,1286,1288],{"href":1287},"\u002Fnuxt-module\u002Fpage-caching#rate-limit-on-cache-misses","rate limit"," allows, and k6 reports the ",[432,1291,1292],{},"429","s as failed requests.",[420,1295,1296,1297,1299],{},"Never leave ",[432,1298,1210],{}," in a live site's allowlist, because it reopens the way past the cache.",[567,1301,1302],{"icon":569,"color":570},[420,1303,1304,1307,1308,1312,1313,929,1316,1319,1320,1323,1324,1326,1327,1329],{},[444,1305,1306],{},"The cache buster must not be a tracking parameter."," The template's Caddyfile drops ",[424,1309,1311],{"href":1310},"\u002Fnuxt-module\u002Fpage-caching#tracking-parameters","tracking parameters"," such as ",[432,1314,1315],{},"utm_source",[432,1317,1318],{},"gclid"," and ",[432,1321,1322],{},"fbclid"," before the cache sees the request, on ",[432,1325,856],{}," too. A buster named like one of those would be stripped even with the allowlist off, and every \"cold\" request would be served from the cache. Keep ",[432,1328,1210],{}," off that list if you edit the script.",[1331,1332,1334],"h3",{"id":1333},"flush-the-cache-after-a-cold-run","Flush the cache after a cold run",[420,1336,1337],{},"Every busted request is stored as its own cache entry. With the default in-memory store, those entries stay until they expire, the cache is flushed or the pod restarts. After a cold test against a real site, flush the cache from the API pod through Caddy's admin port:",[454,1339,1341],{"className":456,"code":1340,"language":458,"meta":459,"style":459},"kubectl exec -n \u003Cnamespace> deploy\u002F\u003Crelease> -- \\\n  curl -s -X PURGE http:\u002F\u002Flocalhost:2019\u002Fsouin-api\u002Fsouin\u002Fflush\n",[432,1342,1343,1383],{"__ignoreMap":459},[463,1344,1345,1348,1351,1354,1356,1359,1362,1365,1368,1371,1374,1376,1378,1381],{"class":465,"line":466},[463,1346,1347],{"class":469},"kubectl",[463,1349,1350],{"class":473}," exec",[463,1352,1353],{"class":520}," -n",[463,1355,553],{"class":552},[463,1357,1358],{"class":473},"namespac",[463,1360,1361],{"class":603},"e",[463,1363,1364],{"class":552},">",[463,1366,1367],{"class":473}," deploy\u002F",[463,1369,1370],{"class":552},"\u003C",[463,1372,1373],{"class":473},"releas",[463,1375,1361],{"class":603},[463,1377,1364],{"class":552},[463,1379,1380],{"class":520}," --",[463,1382,539],{"class":538},[463,1384,1385,1388,1391,1394,1397],{"class":465,"line":484},[463,1386,1387],{"class":473},"  curl",[463,1389,1390],{"class":520}," -s",[463,1392,1393],{"class":520}," -X",[463,1395,1396],{"class":473}," PURGE",[463,1398,1399],{"class":473}," http:\u002F\u002Flocalhost:2019\u002Fsouin-api\u002Fsouin\u002Fflush\n",[420,1401,1402,1403,1406,1407,1410,1411,899],{},"Caddy's admin API listens only inside the container, so run the request there. Locally, that's ",[432,1404,1405],{},"docker compose exec php curl -s -X PURGE http:\u002F\u002Flocalhost:2019\u002Fsouin-api\u002Fsouin\u002Fflush",". The ",[432,1408,1409],{},"silverback:api-components:purge-http-cache"," command does the same flush. See ",[424,1412,1414],{"href":1413},"\u002Fnuxt-module\u002Fpage-caching#purging-all-cached-data","Purging all cached data",[449,1416,1418],{"id":1417},"reading-the-summary","Reading the summary",[420,1420,1421],{},"The script replaces k6's default summary with this:",[454,1423,1428],{"className":1424,"code":1426,"language":1427},[1425],"language-text","=== smoke against https:\u002F\u002Flocalhost (CACHE=cold) ===\nTime to first byte\n  Pages (HTML)         avg 116ms  med 83ms  p95 244ms  max 273ms\n  API (\u002F_api)          avg 19ms  med 1ms  p95 108ms  max 113ms\n  Static (\u002F_nuxt)      avg 6ms  med 6ms  p95 11ms  max 11ms\nSouin cache\n  Pages                0% hits  (hit 0, miss 6, bypass 0, no header 0)\n  API                  83% hits  (hit 10, miss 2, bypass 0, no header 0)\n  => page latency above is mostly SSR rendering (cache misses)\nTotals\n  ...\n","text",[432,1429,1426],{"__ignoreMap":459},[1187,1431,1432,1462,1498,1508],{},[1190,1433,1434,1437,1438],{},[444,1435,1436],{},"Time to first byte"," is split into pages, API calls and static files. A cache hit, a render, an API call and a static file differ too much to average together. Read p95, not the average.\n",[1187,1439,1440,1447,1453],{},[1190,1441,1442,1446],{},[1443,1444,1445],"em",{},"Pages"," measures the cache when hits are high, and Nuxt's SSR when they are low.",[1190,1448,1449,1452],{},[1443,1450,1451],{},"API"," is php behind Souin. Once warm, almost all of these are hits.",[1190,1454,1455,1458,1459,1461],{},[1443,1456,1457],{},"Static"," is Nuxt serving the build's ",[432,1460,852],{}," files. Souin does not cache these.",[1190,1463,1464,1467,1468,1471,1472],{},[444,1465,1466],{},"Souin cache"," counts each response's ",[432,1469,1470],{},"Cache-Status"," header.\n",[1187,1473,1474,1480,1486,1492],{},[1190,1475,1476,1479],{},[432,1477,1478],{},"hit"," was served from the cache.",[1190,1481,1482,1485],{},[432,1483,1484],{},"miss"," was forwarded and stored.",[1190,1487,1488,1491],{},[432,1489,1490],{},"bypass"," means Souin gave up, for example a render slower than its 10-second backend timeout.",[1190,1493,1494,1497],{},[432,1495,1496],{},"no header"," means the request never went through the cache: an excluded path, a cookie, or no Souin in front.",[1190,1499,1500,1507],{},[444,1501,1502,1503,1506],{},"The ",[432,1504,1505],{},"=>"," line"," tells you whether the page numbers measured the cache or SSR.",[1190,1509,1510,1513,1514,1516,1517,1520],{},[444,1511,1512],{},"Thresholds:"," page p95 under ",[432,1515,1139],{},", 99% of pages returning ",[432,1518,1519],{},"200",", API and static p95 under 1 second, and under 1% failed requests. k6 exits non-zero if any of them fail.",[420,1522,1523,1524,1527,1528,1531,1532,899],{},"Requests are tagged ",[432,1525,1526],{},"kind=page|api|asset",", and pages also get ",[432,1529,1530],{},"cache_mode=warm|cold",". The per-kind numbers are available in any k6 output, such as ",[432,1533,1534],{},"--out json=results.json",[567,1536,1538],{"icon":1537},"i-heroicons-information-circle",[420,1539,1540,1543,1544,1547,1548,1551,1552,1555,1556,1560],{},[444,1541,1542],{},"Local warm runs can show misses."," Dev pages expire after 60 seconds, so a warm run that starts more than a minute after the last one begins with misses. On module builds before ",[432,1545,1546],{},"26f06f8d",", the home page ",[432,1549,1550],{},"\u002F"," of the template's fixture data was never cached, because it uses a draft component. Current builds, including ",[432,1553,1554],{},"2.0.0-alpha.4"," which the template pins, cache it (see ",[424,1557,1559],{"href":1558},"\u002Fnuxt-module\u002Fpage-caching#when-a-page-is-not-cached","When a page is not cached",").",[449,1562,1564],{"id":1563},"traps","Traps",[567,1566,1567],{"icon":569,"color":570},[420,1568,1569,1575],{},[444,1570,1571,1572,899],{},"Keep ",[432,1573,1574],{},"Accept-Encoding: gzip"," The script pins it on every request. Caddy prefers brotli or zstd, which k6 cannot decode, and k6 reports an undecodable response just like a server error. One run reported 89% failed requests against a healthy server.",[567,1577,1579],{"icon":1578,"color":570},"i-heroicons-shield-exclamation",[420,1580,1581,1587,1588,929,1591,929,1594,929,1597,1600,1601,929,1604,934,1607,1610],{},[444,1582,1583,1586],{},[432,1584,1585],{},"CONFIRM=yes"," is required for any host that is not local."," Local means ",[432,1589,1590],{},"localhost",[432,1592,1593],{},"127.x.x.x",[432,1595,1596],{},"[::1]",[432,1598,1599],{},"host.docker.internal",", or a name ending in ",[432,1602,1603],{},".local",[432,1605,1606],{},".localhost",[432,1608,1609],{},".test",". The check runs before any request is sent. A surge is a small denial-of-service attack by design. Only test a site you are responsible for, and tell its owners first. Expect the autoscaler to add pods, which costs money, and watch the site while the test runs.",[449,1612,1614],{"id":1613},"next-steps","Next steps",[1187,1616,1617,1623,1629],{},[1190,1618,1619,1622],{},[424,1620,1621],{"href":159},"Page caching",": what a cached page carries and how long it is kept.",[1190,1624,1625,1628],{},[424,1626,1627],{"href":722},"Warming the cache after a deploy",": run a warm test after it, so you measure what visitors get.",[1190,1630,1631,1635],{},[424,1632,1634],{"href":1633},"\u002Fdeployment\u002Fci-cd#auditing-performance-after-a-deploy","Auditing performance after a deploy",": the load test tells you how much traffic the site can take. The audit tells you what a single visitor experiences.",[1637,1638,1639],"style",{},"html pre.shiki code .sRCss, html code.shiki .sRCss{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#FFCB6B}html pre.shiki code .sLL54, html code.shiki .sLL54{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#C3E88D}html pre.shiki code .sTBSN, html code.shiki .sTBSN{--shiki-light:#6A737D;--shiki-light-font-style:inherit;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--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 .szhYu, html code.shiki .szhYu{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#C3E88D}html pre.shiki code .sc2zw, html code.shiki .sc2zw{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#BABED8}html pre.shiki code .sVlFx, html code.shiki .sVlFx{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#89DDFF}html pre.shiki code .sPB8G, html code.shiki .sPB8G{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#BABED8}",{"title":459,"searchDepth":484,"depth":484,"links":1641},[1642,1643,1644,1645,1646,1650,1651,1652],{"id":451,"depth":484,"text":452},{"id":587,"depth":484,"text":588},{"id":746,"depth":484,"text":747},{"id":860,"depth":484,"text":861},{"id":1176,"depth":484,"text":1647,"children":1648},"Cached or rendered: CACHE",[1649],{"id":1333,"depth":627,"text":1334},{"id":1417,"depth":484,"text":1418},{"id":1563,"depth":484,"text":1564},{"id":1613,"depth":484,"text":1614},"Stress test a CWA site with the template's k6 script — how many visitors it serves, how quickly, and whether they got the page cache or a server-side render.","md",{},{"title":402,"description":1653},"OPJcQxOnbj8yhVvgxqOyCBGtJywF7kwj_RHSphudsmE",[1659,1661],{"title":398,"path":399,"stem":400,"description":1660,"children":-1},"The template ships full CI\u002FCD for both GitLab CI and GitHub Actions — Docker Buildx builds, tests, per-branch review apps, and staged Kubernetes deployments via Helm.",{"title":406,"path":407,"stem":408,"description":1662,"children":-1},"When a project's functional test suite slows CI down — measure where the time goes, reset the database without rebuilding the schema, and shard the job by test.",1791209736589]