S

SQL feeder

Data sources & feeders available

Feed rows from a Postgres/MySQL query into the run, shared across VUs.

Install
$ loadr plugin install sql-feeder
examples/plugins/sql-feeder.yaml
# SQL-driven feeder: a native SERVICE plugin runs one SELECT against the
# database at startup and writes the result set to a JSON file, which a normal
# `type: json` data feeder then hands to VUs during the run.
#
# Why a service (not a protocol)? The rows are fetched ONCE, before any VU
# starts, so every VU parameterises requests from live production-shaped data
# without each iteration touching the database. The service ABI's start()/stop()
# lifecycle is exactly this "prepare before the run, clean up after" shape.
#
# SQL support is NOT built into loadr core — `sql-feeder` is a runtime-loadable
# plugin that ships the heavy `sqlx` Rust driver on its own. It serves both
# `postgres://` and `mysql://` URLs (the driver is chosen from the URL scheme).
#
# Build + install the plugin, then run:
#   cargo build -p loadr-plugin-sql-feeder --release
#   mkdir -p dist && cp plugins/loadr-plugin-sql-feeder/plugin.toml dist/ \
#     && cp target/release/libloadr_plugin_sql_feeder.so dist/
#   loadr plugin install dist
#   loadr run examples/plugins/sql-feeder.yaml
#
# Or point the plan's `plugins:` entry at the built artifact directly (below).
name: sql-feeder
description: Seed a JSON data feeder from a live SELECT via the sql-feeder service plugin

plugins:
  # Resolve `sql-feeder` by name from the plugins dir (after `loadr plugin install`).
  # To run straight from a build tree instead, add:
  #   path: target/release/libloadr_plugin_sql_feeder.so
  - name: sql-feeder
    config:
      # postgres:// or mysql:// connection URL.
      url: postgres://loadr:loadr@db.example.com:5432/loadr
      # Any SELECT; each returned column becomes a feeder field. Keep the result
      # bounded — these rows are held in memory and reused across the whole run.
      query: >-
        SELECT id, email, plan
        FROM users
        WHERE active = true
        ORDER BY created_at DESC
        LIMIT 1000
      # Where the rows are written. The `data:` source below reads this file.
      output: data/users-from-db.json

data:
  # The service wrote this file before the run; feed a random account each time.
  account:
    type: json
    path: data/users-from-db.json
    mode: shared
    pick: random

scenarios:
  browse_as_seeded_users:
    executor: constant-arrival-rate
    rate: 50
    duration: 30s
    pre_allocated_vus: 10
    max_vus: 40
    flow:
      - request:
          name: login
          method: POST
          url: https://api.example.com/login
          body:
            json:
              email: ${data.account.email}
          extract:
            - { type: jsonpath, name: token, expression: "$.token" }
          checks:
            - { type: status, equals: 200 }
      - request:
          name: profile
          url: https://api.example.com/users/${data.account.id}
          headers:
            Authorization: Bearer ${token}
          checks:
            - { type: status, equals: 200 }
            - { type: jsonpath, name: plan matches feeder, expression: "$.plan", equals: "${data.account.plan}" }

thresholds:
  checks: [ "rate>0.99" ]
  http_req_duration: [ "p(95)<400ms" ]

A real run: install from the signed index, then watch the plugin work.

A runtime plugin, never in the binary

Installing pulls a per-platform driver from the signed index, verifies its SHA-256 and checks its ABI before it ever loads. Remove it any time with loadr plugin remove sql-feeder.