For the complete documentation index, see llms.txt. This page is also available as Markdown.

Lockable pools

Lease test data that two runs can't share — logins, phone numbers, accounts. One row per run, released at the end.

A lockable pool is a dataset of equal-length lists. Each index across the lists is one row, and a running test leases one row for the length of the run.

Platforms

Android · iOS

A row

The i-th value of every column, leased as one unit

Rule

Every column must be a list, and all columns the same length

Scope

Leases are global — honored across every plan, run and tab at once

Watch out

Pool size caps parallelism. A 4-row pool means at most 4 tests at once

Prerequisites

  • Drizz desktop app installed and signed in

  • A dataset whose every column is a list of the same length

  • A test plan, to lock the variables on

Copy this

The dataset — shopease_logins, with Lockable pool ticked:

phone: ["9000000001", "9000000002", "9000000003", "9000000004"]
otp:   ["123456", "123456", "123456", "123456"]

That is a pool of 4 rows. Row 0 is {phone: 9000000001, otp: 123456}.

The test that leases from it:

The script is identical to a normal dataset-driven test. The difference is in how the plan resolves {{phone}} and {{otp}}.

Data that can't be shared

Data
What happens without a pool

Login credentials

A second login can invalidate the first session

Phone numbers waiting on an OTP

Two runs race for the same message

Accounts mid-flow

One run's cart is the other run's mystery bug

Ten parallel tests against one account produce ten flaky results. A pool gives each run its own row.

Set up a pool

  1. Write every column as a list, all the same length.

  2. Tick Lockable pool in the dataset editor.

  3. Save the dataset.

  4. Open the plan's data step and set each pooled variable's source to lock to a pool.

  5. Run the plan and open the Locks panel to confirm rows are leased and released.

Save rejects a pool that isn't shaped right:

Problem
Message on save

A column isn't a list

Rejected — it names the offending variables

Columns of different lengths

Rejected — it lists the lengths

An empty pool

Rejected — a pool needs at least one row

Single-quoted inline lists (['a', 'b']) don't parse as a list and are caught by the not-a-list check. Use double quotes, or block - items.

A variable that only a pool provides is locked automatically. A variable that both a pool and a normal dataset provide is left to be chosen — nothing is selected silently. Because a row is paired, locking one column also leases the pool's other referenced columns.

Lease behavior

Stage
Behavior

Acquire

The test leases the lowest free row when it starts

Binding

Every column in that row binds into the run. {{phone}} and {{otp}} come from the same index, always paired

Hold

The row is held for the whole run, by at most one run at a time

Release

The row is released when the run finishes — passed, failed or timed out

Scope

Leases are global. A plan, a second plan, and a single test run from the editor draw from one registry, so no two get the same row

Exhaustion

The next run waits rather than failing, with pool_exhausted as the wait reason. It gives up after a timeout and fails with "no free value in pool"

Stale recovery

Leases older than the stale threshold are reclaimed the next time anything tries to acquire a row

Sizing

Pool rows vs parallelism
Result

Rows ≥ maximum parallelism

Every run leases immediately

Rows < maximum parallelism

The extra runs queue. The suite still passes; it takes as long as running at the lower concurrency

Rows > maximum parallelism

No cost. Spare rows sit unleased

A plan that runs 10-wide needs a pool of 10 rows or more.

Several pools at once

A test can lease from more than one pool — credentials from one, phone numbers from another. Lock each variable to its pool.

Rows are acquired all-or-nothing. If one pool is full, whatever was already acquired is released and the run retries, which is what stops two runs deadlocking while each holds half of what it needs.

Each pool independently caps concurrency at its own size. A 2-row credentials pool plus a 2-row phone pool, with six cases needing both, runs at most 2 at a time.

Rules and limits

  • All columns must be the same length, or the pool can't be locked or used at all.

  • A SET in the test wins over a leased value for the same variable. A stray SET phone = "9000000000" silently defeats the pool.

  • Locking gives different values, not the same one. Two runs that must use an identical value take a fixed value from a normal dataset instead.

  • Data-driven looping and lockable pools can't be combined on one plan.

  • Deleting or renaming a pool a saved plan uses stops that plan running until the plan is reopened and pools are chosen again. It never silently leases from somewhere else.

  • Two selected pools providing the same variable is flagged as a conflict and blocks save and run. Untick all but one.

When rows get stuck

A run that dies without releasing — a closed tab, a crashed session — leaves its row held. Two mechanisms recover it:

  • Leases older than the stale threshold are reclaimed automatically the next time anything tries to acquire a row.

  • The Locks panel has Clear stale and Release all, plus a per-row release.

Releasing a row that's still running frees it for reuse while the run continues, so two runs can then share that value. The panel marks running rows and asks for confirmation.

Common mistakes

What you write
What happens

phone as a list, otp as a single value

The pool can't be locked. Every column must be a list

Columns of different lengths

Rejected on save. Even a one-row difference blocks the pool

phone: ['9000000001'] — single quotes inline

Doesn't parse as a list. Use double quotes or block - items

A 4-row pool with concurrency set to 10

Six runs sit waiting. You'll see pool_exhausted

SET phone = "9000000000" in a test that leases phone

The SET wins and every parallel run uses the same number

Expecting two runs to get the same leased row

They never will. Use a fixed value instead

Renaming a pool a saved plan uses

The plan won't run until you reopen it and pick pools again

Next


Last updated: 6 August 2026

Last updated

Was this helpful?