All jobs

Write k6 Load Tests for an Express API

Yes. An agent writes k6 scripts for your Express API's main flows, ramps them against the service in its sandbox and reports p95 latency and the breaking rate.

Run this on RushIn a Project that has your repository.

What the agent does

The agent clones the API into its own cloud sandbox and reads how it starts. In an Express API like gothinkster/node-express-realworld-example-app, package.json pins express ~4.18.1 and @prisma/client ^4.16.1, runs through Nx ("start": "nx serve", "build": "nx build"), and keeps its Prisma schema at src/prisma/schema.prisma with a postgresql datasource read from DATABASE_URL. src/main.ts listens on PORT or 3000, and src/app/routes/routes.ts mounts every controller under /api. So the agent installs Postgres in the sandbox, runs the four migrations under src/prisma/migrations, seeds with src/prisma/seed.ts, builds, and starts the service before writing a line of k6.

It picks three flows from the controllers by what users do most and what costs the server most. Sign-in is POST /api/users/login in auth.controller.ts, and auth.service.ts checks the password with bcrypt.compare on hashes made with bcrypt.hash(password, 10), which is CPU work on every request. Reading is GET /api/articles and GET /api/articles/feed, which join tags, authors and favorites through Prisma. Writing is POST /api/articles behind auth.required. The token comes back in the login response, and auth.ts accepts it as either Token <jwt> or Bearer <jwt>, so the scripts sign in once per virtual user in setup or the first iteration and reuse the token.

Each flow gets its own script in load/: load/login.js, load/read-articles.js and load/create-article.js. Each uses a ramping-arrival-rate scenario, so the request rate rises on a fixed schedule whatever the latency, with checks on status codes and thresholds that mark the run failed when http_req_failed passes rate<0.01. Sign-up data comes from the script itself with unique emails, so repeated runs do not collide on the unique email and username columns.

Then the agent runs each script against the service in the sandbox, reads k6's summary at each stage, and notes the request rate where the error rate first passes 1% and the p95 of http_req_duration just below it. It also watches the Node process: when sign-in breaks first, the CPU time spent in bcrypt is the likely reason, and the report says so as a reading of the numbers, not a proven cause.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Write k6 load tests for this Express API. Read package.json, src/main.ts, the route controllers and the Prisma schema, then start the service in the sandbox with its own database: install Postgres, run the Prisma migrations and the seed, build and start it. Write one k6 script in load/ for each of the three most important flows, including sign-in, using a ramping-arrival-rate scenario, checks on status codes and a threshold on http_req_failed of 1%. Generate unique users in the scripts. Ramp each script until the error rate passes 1% and record the p95 latency and the request rate where errors start. Open a pull request with the scripts, a load/README.md explaining how to run them, and a table per flow of request rate, p95 latency and error rate at each stage.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-api"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a pull request with load/login.js, load/read-articles.js, load/create-article.js and load/README.md. The README says how to start the API with a database, how to point the scripts at another host with an environment variable, and how to read the result. The description carries a table per flow: each ramp stage's request rate, p95 latency and error rate, with the stage where errors passed 1% marked.

The numbers describe the sandbox, a single Node process and a Postgres on the same machine, and the pull request says so. They are a baseline to compare against after a change, not a promise about production. The session's transcript keeps each k6 run with its full summary, so every number in the table can be traced to its output.

Before merging, a reviewer checks that the flows chosen are the ones that matter for the product, that the thresholds match what the team would call failing, and that no script writes to a real database or calls a third-party service when pointed at staging.

Run it on every release candidate

Once the scripts exist, a release job can send a follow-up request that runs them against the release candidate's branch and compares the table with the last one. Put the branch in the resources URL as https://github.com/your-org/your-api/tree/<branch> so the run starts on that code.

With a webhook URL on the API key, Rush posts run.completed when the turn ends and includes the final answer in result up to 16 KiB. Your release job can read the table there and hold the release when the breaking rate dropped.

The use case this job follows, with its automation and trigger: Write the missing tests.

Why run it on Rush?

Load testing on a laptop measures the laptop, and pointing k6 at a shared staging server measures everyone else's traffic too. A Rush sandbox gives the agent its own machine with the API, its database and k6 side by side, nothing else running, so a ramp from low to high rate is the only load there.

The record is the proof: every script run's summary is kept in the transcript, and the table in the pull request is built from those outputs rather than estimated. Separate runs can load-test different services at once, each in its own sandbox, without competing for the same database.

Frequently asked questions

Does it run the load test against my production API?

No. The prompt starts the service inside the sandbox with its own Postgres and points k6 at it. The scripts read their target host from an environment variable, so your team chooses when to run them anywhere else.

Why does sign-in break before reads do?

It may not, but it often does in this kind of API: each login runs bcrypt.compare against a cost-10 hash, which is deliberate CPU work in a single-threaded Node process. The report shows which flow broke first and at what rate, so you can see it rather than assume it.

Will the scripts leave test data behind?

Yes, in the sandbox database, which is thrown away with the run. Against a shared environment they create users and articles, and the README says so, so run them against a database you can reset.

Can I use Artillery or Locust instead of k6?

Name the tool in the prompt and the agent writes and runs that instead. The rest of the job, starting the API with its database and ramping until errors pass 1%, is the same.