[{"data":1,"prerenderedAt":1571},["ShallowReactive",2],{"navigation":3,"\u002Fdeployment\u002Fload-testing":409,"\u002Fdeployment\u002Fload-testing-surround":1566},[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],{"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 Behat Tests","\u002Fdeployment\u002Ffaster-behat-tests","6.deployment\u002F5.faster-behat-tests",{"id":410,"title":402,"badge":411,"body":412,"description":1561,"extension":1562,"links":411,"meta":1563,"navigation":626,"path":403,"seo":1564,"stem":404,"__hash__":1565},"docs\u002F6.deployment\u002F4.load-testing.md",null,{"type":413,"value":414,"toc":1548},"minimark",[415,436,444,449,494,501,553,562,581,585,703,709,725,740,744,843,854,858,864,1170,1176,1182,1214,1223,1251,1256,1259,1321,1336,1340,1343,1351,1442,1456,1469,1473,1484,1519,1523,1544],[416,417,418,419,426,427,431,432,435],"p",{},"The template ships a ",[420,421,425],"a",{"href":422,"rel":423},"https:\u002F\u002Fk6.io",[424],"nofollow","k6"," script at ",[428,429,430],"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 ",[420,433,434],{"href":159},"page cache"," or a fresh server-side render (SSR), because the two differ by orders of magnitude.",[416,437,438,439,443],{},"It is a manual tool. ",[440,441,442],"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.",[445,446,448],"h2",{"id":447},"install-k6","Install k6",[450,451,456],"pre",{"className":452,"code":453,"language":454,"meta":455,"style":455},"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","",[428,457,458,478],{"__ignoreMap":455},[459,460,463,467,471,474],"span",{"class":461,"line":462},"line",1,[459,464,466],{"class":465},"sRCss","brew",[459,468,470],{"class":469},"sLL54"," install",[459,472,473],{"class":469}," k6",[459,475,477],{"class":476},"sTBSN","                      # macOS\n",[459,479,481,484,487,489,491],{"class":461,"line":480},2,[459,482,483],{"class":465},"sudo",[459,485,486],{"class":469}," apt-get",[459,488,470],{"class":469},[459,490,473],{"class":469},[459,492,493],{"class":476},"              # Debian\u002FUbuntu, after adding Grafana's apt repo\n",[416,495,496,497,500],{},"Or skip the install and use Docker. Pass the variables with ",[428,498,499],{},"-e"," and the script on stdin:",[450,502,504],{"className":452,"code":503,"language":454,"meta":455,"style":455},"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",[428,505,506,536],{"__ignoreMap":455},[459,507,508,511,514,518,521,524,527,529,532],{"class":461,"line":462},[459,509,510],{"class":465},"docker",[459,512,513],{"class":469}," run",[459,515,517],{"class":516},"szhYu"," --rm",[459,519,520],{"class":516}," -i",[459,522,523],{"class":516}," -e",[459,525,526],{"class":469}," BASE_URL=https:\u002F\u002Fstaging.example.com",[459,528,523],{"class":516},[459,530,531],{"class":469}," CONFIRM=yes",[459,533,535],{"class":534},"sc2zw"," \\\n",[459,537,538,541,543,546,550],{"class":461,"line":480},[459,539,540],{"class":469},"  grafana\u002Fk6",[459,542,513],{"class":469},[459,544,545],{"class":469}," -",[459,547,549],{"class":548},"sVlFx"," \u003C",[459,551,552],{"class":469}," bin\u002Fload-test\u002Flaunch.js\n",[416,554,555,556,561],{},"See the ",[420,557,560],{"href":558,"rel":559},"https:\u002F\u002Fgrafana.com\u002Fdocs\u002Fk6\u002Flatest\u002Fset-up\u002Finstall-k6\u002F",[424],"k6 install guide"," for other platforms.",[563,564,567],"callout",{"icon":565,"color":566},"i-heroicons-exclamation-triangle","warning",[416,568,569,572,573,576,577,580],{},[440,570,571],{},"Run it from a cloud VM near the cluster, not a laptop."," Use a VM in the same region for anything bigger than ",[428,574,575],{},"smoke",". A laptop runs out of sockets and bandwidth first. At around 300 visitors k6 reports ",[428,578,579],{},"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.",[445,582,584],{"id":583},"run-a-test","Run a test",[450,586,588],{"className":452,"code":587,"language":454,"meta":455,"style":455},"# 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",[428,589,590,595,621,628,634,666],{"__ignoreMap":455},[459,591,592],{"class":461,"line":462},[459,593,594],{"class":476},"# The local stack has a self-signed certificate. Local hosts need no confirmation.\n",[459,596,597,601,604,607,610,612,615,617,619],{"class":461,"line":480},[459,598,600],{"class":599},"sPB8G","BASE_URL",[459,602,603],{"class":548},"=",[459,605,606],{"class":469},"https:\u002F\u002Flocalhost",[459,608,609],{"class":599}," INSECURE",[459,611,603],{"class":548},[459,613,614],{"class":469},"true",[459,616,473],{"class":465},[459,618,513],{"class":469},[459,620,552],{"class":469},[459,622,624],{"class":461,"line":623},3,[459,625,627],{"emptyLinePlaceholder":626},true,"\n",[459,629,631],{"class":461,"line":630},4,[459,632,633],{"class":476},"# Any other host needs CONFIRM=yes.\n",[459,635,637,639,641,644,647,649,652,655,657,660,662,664],{"class":461,"line":636},5,[459,638,600],{"class":599},[459,640,603],{"class":548},[459,642,643],{"class":469},"https:\u002F\u002Fstaging.example.com",[459,645,646],{"class":599}," CONFIRM",[459,648,603],{"class":548},[459,650,651],{"class":469},"yes",[459,653,654],{"class":599}," MODE",[459,656,603],{"class":548},[459,658,659],{"class":469},"capacity",[459,661,473],{"class":465},[459,663,513],{"class":469},[459,665,552],{"class":469},[459,667,669,671,673,676,678,680,682,684,686,689,692,694,697,699,701],{"class":461,"line":668},6,[459,670,600],{"class":599},[459,672,603],{"class":548},[459,674,675],{"class":469},"https:\u002F\u002Fwww.example.com",[459,677,646],{"class":599},[459,679,603],{"class":548},[459,681,651],{"class":469},[459,683,654],{"class":599},[459,685,603],{"class":548},[459,687,688],{"class":469},"surge",[459,690,691],{"class":599}," PEOPLE",[459,693,603],{"class":548},[459,695,696],{"class":469},"300",[459,698,473],{"class":465},[459,700,513],{"class":469},[459,702,552],{"class":469},[416,704,705,706,708],{},"Start with ",[428,707,575],{},". It checks the script, the target and the cache headers before you point real load at anything.",[416,710,711,712,715,716,720,721,724],{},"By default the pages come from ",[428,713,714],{},"\u002Fsitemap.xml",", read the same way as the ",[420,717,719],{"href":718},"\u002Fdeployment\u002Fci-cd#warming-the-cache-after-a-deploy","cache warm after a deploy",". Set ",[428,722,723],{},"PAGES=\u002F,\u002Fabout"," to test specific paths instead.",[563,726,728],{"icon":727},"i-heroicons-photo",[416,729,730,733,734,736,737,739],{},[440,731,732],{},"Image placeholder:"," a terminal showing a ",[428,735,575],{}," run against ",[428,738,606],{},", from the start banner to the summary.",[445,741,743],{"id":742},"modes","Modes",[745,746,747,765],"table",{},[748,749,750],"thead",{},[751,752,753,759,762],"tr",{},[754,755,756],"th",{},[428,757,758],{},"MODE",[754,760,761],{},"What it does",[754,763,764],{},"Use it to",[766,767,768,786,806,825],"tbody",{},[751,769,770,776,783],{},[771,772,773,775],"td",{},[428,774,575],{}," (default)",[771,777,778,779,782],{},"2 visitors for 30s (",[428,780,781],{},"DURATION",")",[771,784,785],{},"Check everything is wired up before a bigger test.",[751,787,788,792,803],{},[771,789,790],{},[428,791,659],{},[771,793,794,795,798,799,802],{},"Steps the arrival rate up to ",[428,796,797],{},"PEAK_RATE"," visitors per second, ",[428,800,801],{},"STAGE"," (30s) per step, then holds.",[771,804,805],{},"Find the point where latency runs away. Size your pods against this.",[751,807,808,812,822],{},[771,809,810],{},[428,811,688],{},[771,813,814,815,818,819,821],{},"Ramps to ",[428,816,817],{},"PEOPLE"," visitors over 60s, holds for 3m (",[428,820,781],{},"), then ramps down.",[771,823,824],{},"Test a launch moment: a URL on a screen and a room reaching for their phones.",[751,826,827,832,840],{},[771,828,829],{},[428,830,831],{},"soak",[771,833,834,837,838,782],{},[428,835,836],{},"PEOPLE \u002F 6"," visitors for 15m (",[428,839,781],{},[771,841,842],{},"Catch leaks and slow degradation under steady traffic.",[416,844,845,846,849,850,853],{},"Each visitor loads a page and its ",[428,847,848],{},"\u002F_nuxt"," files, then reads for 2–6 seconds. Next it makes one client-side navigation, which in CWA is two ",[428,851,852],{},"\u002F_api"," calls (the route and its resource manifest), not another server render. Then it reads for 3–9 seconds more.",[445,855,857],{"id":856},"environment-variables","Environment variables",[416,859,860,861,863],{},"Only ",[428,862,600],{}," is required.",[745,865,866,879],{},[748,867,868],{},[751,869,870,873,876],{},[754,871,872],{},"Variable",[754,874,875],{},"Default",[754,877,878],{},"Meaning",[766,880,881,896,911,933,959,982,1000,1020,1033,1048,1066,1095,1111,1129,1144,1158],{},[751,882,883,887,890],{},[771,884,885],{},[428,886,600],{},[771,888,889],{},"(required)",[771,891,892,893,895],{},"Site origin, such as ",[428,894,675],{},".",[751,897,898,903,905],{},[771,899,900],{},[428,901,902],{},"CONFIRM",[771,904],{},[771,906,907,908,910],{},"Must be ",[428,909,651],{}," for any host that is not local.",[751,912,913,917,921],{},[771,914,915],{},[428,916,758],{},[771,918,919],{},[428,920,575],{},[771,922,923,925,926,925,928,930,931,895],{},[428,924,575],{},", ",[428,927,659],{},[428,929,688],{}," or ",[428,932,831],{},[751,934,935,939,944],{},[771,936,937],{},[428,938,817],{},[771,940,941],{},[428,942,943],{},"100",[771,945,946,947,949,950,952,953,955,956,958],{},"Simultaneous visitors for ",[428,948,688],{},". ",[428,951,831],{}," uses a sixth of it, and ",[428,954,659],{}," derives ",[428,957,797],{}," from it.",[751,960,961,966,971],{},[771,962,963],{},[428,964,965],{},"CACHE",[771,967,968],{},[428,969,970],{},"warm",[771,972,973,925,975,930,978,981],{},[428,974,970],{},[428,976,977],{},"cold",[428,979,980],{},"mixed",". See below.",[751,983,984,989,994],{},[771,985,986],{},[428,987,988],{},"COLD_RATIO",[771,990,991],{},[428,992,993],{},"0.2",[771,995,996,997,895],{},"Share of page loads that bust the cache when ",[428,998,999],{},"CACHE=mixed",[751,1001,1002,1007,1012],{},[771,1003,1004],{},[428,1005,1006],{},"COLD_API",[771,1008,1009],{},[428,1010,1011],{},"false",[771,1013,1014,1016,1017,1019],{},[428,1015,614],{}," also busts the cache on the ",[428,1018,852],{}," calls in cold and mixed loads.",[751,1021,1022,1027,1030],{},[771,1023,1024],{},[428,1025,1026],{},"PAGES",[771,1028,1029],{},"the sitemap",[771,1031,1032],{},"Comma-separated paths to test instead of the sitemap.",[751,1034,1035,1040,1045],{},[771,1036,1037],{},[428,1038,1039],{},"MAX_PAGES",[771,1041,1042],{},[428,1043,1044],{},"50",[771,1046,1047],{},"Most pages taken from the sitemap.",[751,1049,1050,1055,1060],{},[771,1051,1052],{},[428,1053,1054],{},"MAX_ASSETS",[771,1056,1057],{},[428,1058,1059],{},"12",[771,1061,1062,1063,1065],{},"Most ",[428,1064,848],{}," files fetched per page load.",[751,1067,1068,1072,1084],{},[771,1069,1070],{},[428,1071,781],{},[771,1073,1074,1077,1078,1077,1081],{},[428,1075,1076],{},"30s"," \u002F ",[428,1079,1080],{},"3m",[428,1082,1083],{},"15m",[771,1085,1086,1087,1089,1090,1092,1093,895],{},"Length of ",[428,1088,575],{},", of the ",[428,1091,688],{}," hold, or of ",[428,1094,831],{},[751,1096,1097,1101,1105],{},[771,1098,1099],{},[428,1100,801],{},[771,1102,1103],{},[428,1104,1076],{},[771,1106,1107,1108,1110],{},"Length of each ",[428,1109,659],{}," step.",[751,1112,1113,1117,1123],{},[771,1114,1115],{},[428,1116,797],{},[771,1118,1119,1122],{},[428,1120,1121],{},"PEOPLE \u002F 7",", at least 2",[771,1124,1125,1126,1128],{},"The top arrival rate for ",[428,1127,659],{},", in visitors per second.",[751,1130,1131,1136,1141],{},[771,1132,1133],{},[428,1134,1135],{},"PAGE_P95_MS",[771,1137,1138],{},[428,1139,1140],{},"2000",[771,1142,1143],{},"Threshold for the p95 time to first byte of pages.",[751,1145,1146,1151,1153],{},[771,1147,1148],{},[428,1149,1150],{},"INSECURE",[771,1152],{},[771,1154,1155,1157],{},[428,1156,614],{}," skips TLS verification. Use it only for the local self-signed stack.",[751,1159,1160,1165,1167],{},[771,1161,1162],{},[428,1163,1164],{},"SUMMARY_JSON",[771,1166],{},[771,1168,1169],{},"Also write k6's full summary data to this file.",[445,1171,1173,1174],{"id":1172},"cached-or-rendered-cache","Cached or rendered: ",[428,1175,965],{},[416,1177,1178,1179,1181],{},"Page HTML and ",[428,1180,852],{}," 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:",[1183,1184,1185,1193,1204],"ul",{},[1186,1187,1188,1192],"li",{},[440,1189,1190],{},[428,1191,970],{}," 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.",[1186,1194,1195,1199,1200,1203],{},[440,1196,1197],{},[428,1198,977],{}," adds a unique ",[428,1201,1202],{},"k6cb="," value to each page request, so every one misses the cache and is rendered by Nuxt. This is the cost of SSR, and the worst case after a purge or a deploy.",[1186,1205,1206,1210,1211,1213],{},[440,1207,1208],{},[428,1209,980],{}," makes ",[428,1212,988],{}," of page loads cold and the rest warm.",[416,1215,1216,1217,1219,1220,895],{},"The navigation's ",[428,1218,852],{}," calls stay cacheable unless you set ",[428,1221,1222],{},"COLD_API=true",[563,1224,1225],{"icon":565,"color":566},[416,1226,1227,1230,1231,1235,1236,925,1239,1242,1243,1246,1247,1250],{},[440,1228,1229],{},"The cache buster must not be a tracking parameter."," The template's Caddyfile drops ",[420,1232,1234],{"href":1233},"\u002Fnuxt-module\u002Fpage-caching#tracking-parameters","tracking parameters"," such as ",[428,1237,1238],{},"utm_source",[428,1240,1241],{},"gclid"," and ",[428,1244,1245],{},"fbclid"," before the cache sees the request. A buster named like one of those would be stripped, and every \"cold\" request would be served from the cache. ",[428,1248,1249],{},"k6cb"," is not on that list, so it stays in the cache key. Keep it that way if you edit the script.",[1252,1253,1255],"h3",{"id":1254},"flush-the-cache-after-a-cold-run","Flush the cache after a cold run",[416,1257,1258],{},"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:",[450,1260,1262],{"className":452,"code":1261,"language":454,"meta":455,"style":455},"kubectl exec -n \u003Cnamespace> deploy\u002F\u003Crelease> -- \\\n  curl -s -X PURGE http:\u002F\u002Flocalhost:2019\u002Fsouin-api\u002Fsouin\u002Fflush\n",[428,1263,1264,1304],{"__ignoreMap":455},[459,1265,1266,1269,1272,1275,1277,1280,1283,1286,1289,1292,1295,1297,1299,1302],{"class":461,"line":462},[459,1267,1268],{"class":465},"kubectl",[459,1270,1271],{"class":469}," exec",[459,1273,1274],{"class":516}," -n",[459,1276,549],{"class":548},[459,1278,1279],{"class":469},"namespac",[459,1281,1282],{"class":599},"e",[459,1284,1285],{"class":548},">",[459,1287,1288],{"class":469}," deploy\u002F",[459,1290,1291],{"class":548},"\u003C",[459,1293,1294],{"class":469},"releas",[459,1296,1282],{"class":599},[459,1298,1285],{"class":548},[459,1300,1301],{"class":516}," --",[459,1303,535],{"class":534},[459,1305,1306,1309,1312,1315,1318],{"class":461,"line":480},[459,1307,1308],{"class":469},"  curl",[459,1310,1311],{"class":516}," -s",[459,1313,1314],{"class":516}," -X",[459,1316,1317],{"class":469}," PURGE",[459,1319,1320],{"class":469}," http:\u002F\u002Flocalhost:2019\u002Fsouin-api\u002Fsouin\u002Fflush\n",[416,1322,1323,1324,1327,1328,1331,1332,895],{},"Caddy's admin API listens only inside the container, so run the request there. Locally, that's ",[428,1325,1326],{},"docker compose exec php curl -s -X PURGE http:\u002F\u002Flocalhost:2019\u002Fsouin-api\u002Fsouin\u002Fflush",". The ",[428,1329,1330],{},"silverback:api-components:purge-http-cache"," command does the same flush. See ",[420,1333,1335],{"href":1334},"\u002Fnuxt-module\u002Fpage-caching#purging-all-cached-data","Purging all cached data",[445,1337,1339],{"id":1338},"reading-the-summary","Reading the summary",[416,1341,1342],{},"The script replaces k6's default summary with this:",[450,1344,1349],{"className":1345,"code":1347,"language":1348},[1346],"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",[428,1350,1347],{"__ignoreMap":455},[1183,1352,1353,1383,1419,1429],{},[1186,1354,1355,1358,1359],{},[440,1356,1357],{},"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",[1183,1360,1361,1368,1374],{},[1186,1362,1363,1367],{},[1364,1365,1366],"em",{},"Pages"," measures the cache when hits are high, and Nuxt's SSR when they are low.",[1186,1369,1370,1373],{},[1364,1371,1372],{},"API"," is php behind Souin. Once warm, almost all of these are hits.",[1186,1375,1376,1379,1380,1382],{},[1364,1377,1378],{},"Static"," is Nuxt serving the build's ",[428,1381,848],{}," files. Souin does not cache these.",[1186,1384,1385,1388,1389,1392,1393],{},[440,1386,1387],{},"Souin cache"," counts each response's ",[428,1390,1391],{},"Cache-Status"," header.\n",[1183,1394,1395,1401,1407,1413],{},[1186,1396,1397,1400],{},[428,1398,1399],{},"hit"," was served from the cache.",[1186,1402,1403,1406],{},[428,1404,1405],{},"miss"," was forwarded and stored.",[1186,1408,1409,1412],{},[428,1410,1411],{},"bypass"," means Souin gave up, for example a render slower than its 10-second backend timeout.",[1186,1414,1415,1418],{},[428,1416,1417],{},"no header"," means the request never went through the cache: an excluded path, a cookie, or no Souin in front.",[1186,1420,1421,1428],{},[440,1422,1423,1424,1427],{},"The ",[428,1425,1426],{},"=>"," line"," tells you whether the page numbers measured the cache or SSR.",[1186,1430,1431,1434,1435,1437,1438,1441],{},[440,1432,1433],{},"Thresholds:"," page p95 under ",[428,1436,1135],{},", 99% of pages returning ",[428,1439,1440],{},"200",", API and static p95 under 1 second, and under 1% failed requests. k6 exits non-zero if any of them fail.",[416,1443,1444,1445,1448,1449,1452,1453,895],{},"Requests are tagged ",[428,1446,1447],{},"kind=page|api|asset",", and pages also get ",[428,1450,1451],{},"cache_mode=warm|cold",". The per-kind numbers are available in any k6 output, such as ",[428,1454,1455],{},"--out json=results.json",[563,1457,1459],{"icon":1458},"i-heroicons-information-circle",[416,1460,1461,1464,1465,1468],{},[440,1462,1463],{},"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 the template's fixture data, the home page ",[428,1466,1467],{},"\u002F"," is never cached, because it uses a draft component.",[445,1470,1472],{"id":1471},"traps","Traps",[563,1474,1475],{"icon":565,"color":566},[416,1476,1477,1483],{},[440,1478,1479,1480,895],{},"Keep ",[428,1481,1482],{},"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.",[563,1485,1487],{"icon":1486,"color":566},"i-heroicons-shield-exclamation",[416,1488,1489,1495,1496,925,1499,925,1502,925,1505,1508,1509,925,1512,930,1515,1518],{},[440,1490,1491,1494],{},[428,1492,1493],{},"CONFIRM=yes"," is required for any host that is not local."," Local means ",[428,1497,1498],{},"localhost",[428,1500,1501],{},"127.x.x.x",[428,1503,1504],{},"[::1]",[428,1506,1507],{},"host.docker.internal",", or a name ending in ",[428,1510,1511],{},".local",[428,1513,1514],{},".localhost",[428,1516,1517],{},".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.",[445,1520,1522],{"id":1521},"next-steps","Next steps",[1183,1524,1525,1531,1537],{},[1186,1526,1527,1530],{},[420,1528,1529],{"href":159},"Page caching",": what a cached page carries and how long it is kept.",[1186,1532,1533,1536],{},[420,1534,1535],{"href":718},"Warming the cache after a deploy",": run a warm test after it, so you measure what visitors get.",[1186,1538,1539,1543],{},[420,1540,1542],{"href":1541},"\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.",[1545,1546,1547],"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":455,"searchDepth":480,"depth":480,"links":1549},[1550,1551,1552,1553,1554,1558,1559,1560],{"id":447,"depth":480,"text":448},{"id":583,"depth":480,"text":584},{"id":742,"depth":480,"text":743},{"id":856,"depth":480,"text":857},{"id":1172,"depth":480,"text":1555,"children":1556},"Cached or rendered: CACHE",[1557],{"id":1254,"depth":623,"text":1255},{"id":1338,"depth":480,"text":1339},{"id":1471,"depth":480,"text":1472},{"id":1521,"depth":480,"text":1522},"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":1561},"3WPr5IYFFMN3JzjKTV1bG8sjGXyP2APgVuVo1HOoYzk",[1567,1569],{"title":398,"path":399,"stem":400,"description":1568,"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":1570,"children":-1},"When a project's Behat suite slows CI down — measure where the time goes, reset the database without rebuilding the schema, and shard the job by scenario.",1790419987229]