before & after Expressions — Complete Examples

before and after are lifecycle hooks: ordered lists of expressions run for their side-effects (usually $find(..., variable=x) or the declarative methods with variable=).

  • before runs before an iteration's/request's skipIf, URL, and headers — a pre‑execution hook for preparing data.
  • after runs after the iteration/request executes — a post‑execution hook, so it can read the response and captured variables and prepare data for the next step.

When after runs

  • Request-level: after the request finishes (including its retries). It runs on both success and failure, but not when skipIf skipped the request, and not on cancellation.
  • Iteration-level: after the iteration completes successfully.

All examples capture the public jsonplaceholder users array first, then use before/after.

Iteration-level before, then verify with skipIf

Two finds run in order at the start of the iteration; skipIf then verifies the result.

name: BeforeDemo
rounds:
  - name: FeatureRound
    numberOfClients: 3
    arrivalDelay: 1000
    runInParallel: false
    iterations:
      - name: getUsers
        httpRequest:
          capture:
            to: users
            as: Json
            makeGlobal: true
          url: https://jsonplaceholder.typicode.com/users
          method: GET

      - name: useMatchedUser
        before:
          - '$find(source=$users.Body, where=item.company.name == "Romaguera-Crona", match=first, variable=matchedUser)'
          - '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=uid)'
        # skipIf skips when TRUE, so this runs only when the match is who we expect.
        skipIf: '${uid} != 1 or "${matchedUser.username}" != "Bret"'
        httpRequest:
          url: 'https://jsonplaceholder.typicode.com/users/${matchedUser.id}/todos'
          method: GET

Request-level before

The setup runs right before this specific request is sent.

name: BeforeRequestDemo
rounds:
  - name: FeatureRound
    numberOfClients: 1
    arrivalDelay: 1000
    runInParallel: false
    iterations:
      - name: getUsers
        httpRequest:
          capture:
            to: users
            as: Json
            makeGlobal: true
          url: https://jsonplaceholder.typicode.com/users
          method: GET

      - name: getAlbums
        httpRequest:
          before:
            - '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
          url: 'https://jsonplaceholder.typicode.com/users/${userId}/albums'
          method: GET

Several expressions in order

before is a list; expressions run top to bottom, and a later one can use what an earlier one stored.

name: BeforeChainDemo
rounds:
  - name: FeatureRound
    numberOfClients: 1
    arrivalDelay: 1000
    runInParallel: false
    iterations:
      - name: getUsers
        httpRequest:
          capture:
            to: users
            as: Json
            makeGlobal: true
          url: https://jsonplaceholder.typicode.com/users
          method: GET

      - name: doWork
        before:
          - '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
          - '$find(source=$users.Body, where=item.username == "Bret", select=item.company.name, match=first, variable=companyName)'
          - '$find(source=$users.Body, where=item.id > 5, match=count, variable=bigUserCount)'
        httpRequest:
          headers:
            X-Company: '${companyName}'
            X-Big-Users: '${bigUserCount}'
          url: 'https://jsonplaceholder.typicode.com/users/${userId}/albums'
          method: GET

after: post-execution hook (request-level)

after runs once the request has completed and its response is captured, so it can extract data from this response for a later step. Here it captures the user, then after pulls a field out of the response body.

name: AfterRequestDemo
rounds:
  - name: FeatureRound
    numberOfClients: 1
    arrivalDelay: 1000
    runInParallel: false
    iterations:
      - name: getUser
        httpRequest:
          capture:
            to: user
            as: Json
            makeGlobal: true
          url: https://jsonplaceholder.typicode.com/users/1
          method: GET
          after:
            - '$setvariable(variable=userCity, value=${user.Body.address.city})'
            - '$find(source=$user.Body.address, where=item.zipcode != "", select=item.zipcode, match=first, variable=userZip)'

      - name: useAfterResults
        httpRequest:
          headers:
            X-User-City: '${userCity}'
            X-User-Zip: '${userZip}'
          url: https://jsonplaceholder.typicode.com/posts/1
          method: GET

after: post-execution hook (iteration-level)

Iteration-level after runs after the iteration completes successfully. Use it to compute roll-up values from what the iteration produced.

name: AfterIterationDemo
rounds:
  - name: FeatureRound
    numberOfClients: 1
    arrivalDelay: 1000
    runInParallel: false
    iterations:
      - name: getUsers
        after:
          - '$find(source=$users.Body, where=item.id > 5, match=count, variable=bigUserCount)'
          - '$greaterthan(a=${bigUserCount}, b=3, variable=hasManyUsers)'
        httpRequest:
          capture:
            to: users
            as: Json
            makeGlobal: true
          url: https://jsonplaceholder.typicode.com/users
          method: GET

before + after together

before prepares inputs, the request runs, then after post-processes the response — a full pre/post pipeline around a single request.

name: BeforeAfterDemo
rounds:
  - name: FeatureRound
    numberOfClients: 1
    arrivalDelay: 1000
    runInParallel: false
    iterations:
      - name: getUsers
        httpRequest:
          capture:
            to: users
            as: Json
            makeGlobal: true
          url: https://jsonplaceholder.typicode.com/users
          method: GET

      - name: process
        httpRequest:
          before:
            - '$find(source=$users.Body, where=item.username == "Bret", select=item.id, match=first, variable=userId)'
          capture:
            to: todos
            as: Json
            makeGlobal: true
          url: 'https://jsonplaceholder.typicode.com/users/${userId}/todos'
          method: GET
          after:
            - '$find(source=$todos.Body, where=item.completed == true, match=count, variable=completedCount)'
            - '$find(source=$todos.Body, match=count, variable=totalCount)'
            - '$divide(a=${completedCount}, b=${totalCount}, variable=completionRatio)'