---
title: "Design a soak profile | Grafana Labs"
description: "Build a k6 soak script with stages that hold average-load levels through a long plateau."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Design a soak profile

The k6 [Soak testing](/docs/k6/latest/testing-guides/test-types/soak-testing/) guide reuses an average-load script and lengthens the plateau. The shape is ramp up, hold at average load, ramp down. Duration on the plateau is what changes between average-load and soak work.

If you use Grafana Cloud with Grafana Assistant enabled, refer to [Use k6 Script Authoring mode](/docs/grafana-cloud/testing/k6/author-run/k6-script-authoring-mode/) to draft or refine a script from a description. The steps below build `soak.js` in your editor so you can follow the profile structure line by line.

To design a soak profile, complete the following steps:

1. Create `soak.js` and add imports:
   
   JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```javascript
   import http from 'k6/http';
   import { check, sleep } from 'k6';
   ```
2. Define `stages` and thresholds.
   
   Set `target` to the VU count from your baseline or average-load test. While learning this path, use a **30-minute** plateau; extend the middle stage for production soaks (for example 2 to 8 hours):
   
   JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```javascript
   export const options = {
     stages: [
       { duration: '2m', target: 15 }, // ramp up to average-load level
       { duration: '30m', target: 15 }, // soak plateau (learning duration)
       { duration: '2m', target: 0 }, // ramp down
     ],
     thresholds: {
       http_req_duration: ['p(95)<500'],
       http_req_failed: ['rate<0.01'],
     },
   };
   ```
   
   If your baseline test runs at 20 VUs, 15 VUs is a moderate plateau below peak. Adjust `target` to match the average-load level you measured. Use `http_req_failed` for pass/fail on HTTP errors; keep checks in the default function for summary visibility. Thresholds are tighter than in a stress test because load is moderate—a breach during the plateau often points to time-dependent degradation rather than overload.
3. Add the default function with the same checks as your baseline test:
   
   JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```javascript
   export default function () {
     const res = http.get('https://quickpizza.grafana.com');
   
     check(res, {
       'status is 200': (r) => r.status === 200,
       'response body is not empty': (r) => r.body && r.body.length > 0,
     });
   
     sleep(1);
   }
   ```
   
   Replace the URL with the endpoint you used in baseline testing. When a request fails (for example a connection reset), k6 may not set `body`. The `r.body &&` guard returns `false` for that check instead of throwing a script error.
4. Save `soak.js`. Your complete file combines the `options` block and default function:
   
   JavaScript ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```javascript
   import http from 'k6/http';
   import { check, sleep } from 'k6';
   
   export const options = {
     stages: [
       { duration: '2m', target: 15 },
       { duration: '30m', target: 15 },
       { duration: '2m', target: 0 },
     ],
     thresholds: {
       http_req_duration: ['p(95)<500'],
       http_req_failed: ['rate<0.01'],
     },
   };
   
   export default function () {
     const res = http.get('https://quickpizza.grafana.com');
   
     check(res, {
       'status is 200': (r) => r.status === 200,
       'response body is not empty': (r) => r.body && r.body.length > 0,
     });
   
     sleep(1);
   }
   ```
   
   The `30m` plateau keeps this path practical for learning. Production soaks commonly use 3, 4, 8, 12, or 24 hours on the middle stage, as noted in the soak test-type guide. Extend duration after you confirm the workflow end to end.

In the next milestone, you configure cloud streaming and degradation thresholds so you can observe the run while it is in progress.
