Load Simulation

Load simulations describe how traffic should arrive over time. Use them to model the shape of the workload instead of only its peak.

What this page helps you do

What this page helps you do

Load simulations describe how traffic should arrive over time. Use them to model the shape of the workload instead of only its peak.

Who this is for

Engineers writing or reviewing scenario code in one of the supported SDKs.

Prerequisites

  • A scenario or runtime surface you want to wire correctly in code

By the end

The exact SDK surface you need for this part of the runtime.

Use this page when

Use this reference when you already know the workflow and need the exact Load Simulation API surface in code.

Visual guide

Load simulation flow showing warmup, ramp, steady load, and stop conditions.
Load simulation settings shape when work starts, ramps, steadies, pauses, and stops.

Guide

Time-Based Simulations

Use duration-based simulations when you want traffic to run for a period of time. Inject(rate, interval, during), InjectRandom(minRate, maxRate, interval, during), RampingInject(rate, interval, during), KeepConstant(copies, during), RampingConstant(copies, during), and Pause(during) all fit that model.

Iteration-Based Simulations

Use iteration-based simulations when you care about a fixed amount of work rather than a fixed duration. IterationsForInject(rate, interval, iterations) and IterationsForConstant(copies, iterations) stop after the configured number of execution cycles.

Traffic Mixes

When one total load profile needs to be split across different business paths, use the Traffic Mix page under Library Options. Keep this page for the primitive load shapes that a scenario or traffic mix can reuse.

Parameter Fields

rate, minRate, and maxRate control request emission intensity. copies controls concurrent virtual users. interval controls pacing, during controls time, and iterations controls total execution cycles. Helper APIs also expose IsInject, IsInjectRandom, IsIterationsForInject, IsIterationsForConstant, and related flags plus string formatting helpers on returned simulation definitions.

Explicit Load Engine V2

Call UseLoadEngineV2, useLoadEngineV2, or use_load_engine_v2 on the runner before Run when you want the versioned smooth-pacing and bounded-work contract. Existing runs that do not opt in keep their legacy behavior. In V2, registered scenarios run concurrently, a rate means scenario invocations per supplied interval, and arrivals are spread across that interval instead of being released as one interval-sized burst. Final scenario results remain in registration order. Weighted traffic mixes retain one global rank space across their lanes and agent shards.

V2 Compatibility Guardrails

Weighted traffic mixes are supported by V2. Cross-platform correlation and remote cluster execution remain capability-gated by SDK and execution mode; an unsupported combination is rejected before traffic instead of silently falling back to partial scheduling or accounting.

Process Capacity

V2 uses a process-wide MaxInFlight ceiling shared by the scenarios and logical agents running in that process. The default is 10,000; tune it with WithMaxInFlight, withMaxInFlight, or with_max_in_flight only after measuring generator CPU, memory, connection pools, broker clients, and target limits. A local cluster still shares the same machine capacity.

Bounded Step Series

Declare statically known step names before a V2 run when you need empty report series for steps that receive no observations. An unexpected runtime step is folded into the bounded <other> series, preventing unbounded report cardinality while preserving its measurements.

Offered And Achieved Load

Offered load is the schedule the test asks the generator to deliver. Achieved load is the work that actually starts. When the generator is late or its in-flight ceiling is full, V2 drops that arrival and records a generator warning instead of adding an unbounded backlog or turning the event into an application failure. Review delivery percentage and scheduler lag beside response latency before treating an RPS target as achieved.

Generator Delivery Report

When scheduler delivery data, raw observation delivery statistics, generator or reporting warnings, or incomplete reporting are available, the HTML report adds a Generator Delivery tab. Use it to review scheduling and reporting health beside application results. If an older result does not include reporting-completeness status, the tab shows N/A instead of reporting loss. Application failures remain separate from generator and reporting warnings.

Observation Completion

Each sink receives its raw iteration batches before its own stream completion marker, and a healthy sink can complete independently while another sink is still draining. If a sink write is still active when the bounded drain period expires, reporting is marked incomplete and no completion marker is sent ahead of that write. The active write is not falsely reported as dropped.

Invocations Versus Transport Work

One scenario invocation is not automatically one wire request or one broker record. A scenario may contain several HTTP steps, publish several Kafka records, or drive a complete browser journey. For Kafka, report records per second and bytes per second alongside invocation rate. For Playwright, size copies for browser contexts and host capacity rather than API-style request rates.

Safe Capacity Runs

Capacity is specific to the generator hardware, runtime, topology, scenario code, and target environment. Start with a small smoke rate, use timeouts and reusable clients, increase gradually, and retain the run configuration and report artifacts. The canonical scheduler-noop/2 profile exercises each SDK's native asynchronous scheduler with a five-second warm-up and 30-second measurement, exact lifecycle accounting, bounded percentile evidence, final-artifact reconstruction, and an inclusive +/-2% offered-and-started-rate boundary. Scheduler-late and MaxInFlight drops are reported separately and prevent certification. Only run high-rate tests against systems you own or have explicit permission to test.

Runtime Stop Control

Load shape is not the only stop signal. Use context.StopScenario(...) when one scenario should end early after the runtime has observed enough data, or context.StopCurrentTest(...) when the whole run should stop because a critical runtime condition has been reached.

Composition

Attach multiple simulations in order with WithLoadSimulations when one scenario needs warm-up, ramp-up, steady-state, and cooldown phases in a single definition.

SDK reference samples

Use these SDK samples to compare how Load Simulation is exposed across the supported languages before you wire it into a full scenario.

If you run these examples locally, add a valid runner key before execution starts. Set it with WithRunnerKey("...") or the config key LoadStrike:RunnerKey.

Load Simulations

using LoadStrike;

var httpClient = new HttpClient
{
    BaseAddress = new Uri("https://api.example.com")
};

var scenario = LoadStrikeScenario.Create("submit-orders", async context =>
{
    var step = await LoadStrikeStep.Run<string>("POST /orders", context, async () =>
    {
        using var response = await httpClient.PostAsJsonAsync("/orders", new
        {
            orderId = $"ord-{context.InvocationNumber}",
            amount = 49.95m
        });

        return response.IsSuccessStatusCode
            ? LoadStrikeResponse.Ok<string>(statusCode: ((int)response.StatusCode).ToString())
            : LoadStrikeResponse.Fail<string>(statusCode: ((int)response.StatusCode).ToString());
    });

    return step.AsReply();
})
.WithLoadSimulations(
    LoadStrikeSimulation.Inject(5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(20)),
    LoadStrikeSimulation.RampingInject(20, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(20)),
    LoadStrikeSimulation.KeepConstant(8, TimeSpan.FromSeconds(20))
);

LoadStrikeRunner.RegisterScenarios(scenario)
    .UseLoadEngineV2()
    .WithMaxInFlight(5000)
    .WithRunnerKey("rkl_your_local_runner_key")
    .Run();

Supported Simulations

Inject

Emit requests at a fixed rate per interval for a fixed duration.

InjectRandom

Vary the request rate between a minimum and maximum value each interval to simulate uneven live traffic.

RampingInject

Increase the request rate progressively over time instead of keeping it flat from the start.

KeepConstant

Run a fixed number of concurrent copies for the requested duration.

RampingConstant

Increase the number of concurrent copies gradually until the target steady-state concurrency is reached.

Pause

Insert a quiet gap between simulation phases without ending the scenario definition.

IterationsForInject

Run an inject-style rate pattern for a fixed number of iterations instead of a time window.

IterationsForConstant

Run a fixed concurrency pattern for a fixed number of iterations instead of a duration.

UseLoadEngineV2 / useLoadEngineV2 / use_load_engine_v2

Explicitly selects the versioned smooth-pacing and bounded-work contract. Registered scenarios run concurrently and final results retain registration order. Runs that do not opt in retain their legacy scheduling behavior.

WithMaxInFlight / withMaxInFlight / with_max_in_flight

Sets the process-wide in-flight ceiling after V2 is selected. The V2 default is 10,000 and valid values are 1 through 1,000,000.

Declared steps

Freeze statically known V2 step series before the run. Declared steps remain visible with zero observations, while an unexpected runtime step is folded into the bounded <other> series.

Generator warning

A late or capacity-blocked arrival is dropped and disclosed as generator under-delivery. It does not become a response failure from the system under test.

Warm-up duration

Warm-up invocations continue for the configured duration and are excluded from measured scenario request, success, and failure totals.

Scenario callback failures

An exception from one scenario invocation is retained as a failed final observation instead of disappearing from the run. Cleanup failures are isolated so later scenarios can still execute.

Observation completion

Each sink receives its raw batches before its own stream completion marker. A healthy sink can complete independently while another sink is still draining. A raw-batch sink must implement the completion callback to prove complete delivery; a missing callback or a write that exceeds the bounded drain period marks that delivery incomplete with a warning.

Generator Delivery tab

Appears in HTML reports when scheduler delivery data, raw observation delivery statistics, generator or reporting warnings, or incomplete reporting are available. Results without reporting-completeness status show N/A rather than reporting loss. Application failures remain separate from generator and reporting warnings.

scheduler-noop/2 capacity evidence

The repository capacity runner exercises each SDK's native asynchronous scheduler with a five-second warm-up and 30-second measurement. It verifies exact lifecycle accounting, bounded percentile evidence, final-artifact reconstruction, and an inclusive +/-2% offered-and-started-rate boundary. Scheduler-late and MaxInFlight drops are shown separately and prevent certification.

context.StopScenario(...) / context.StopCurrentTest(...)

Use runtime stop helpers when the workload should end because the scenario observed enough evidence or because the whole test must stop early for a critical condition.

Choose rate-based simulations when you care about scenario invocations per interval and copy-based simulations when you care about concurrent workload copies. One invocation can issue multiple HTTP requests, Kafka records, or browser operations, so compare offered load with achieved transport throughput. Use the Traffic Mix page when one shared total load should be distributed across multiple business paths.