Scaffold#

The edg scaffold command is an interactive wizard that generates a complete workload config. It walks you through driver selection, table definitions, and column types, then outputs valid YAML to stdout.

edg scaffold > workload.yaml

Walkthrough#

The wizard prompts for three things:

  1. Database driver - select from pgx, mysql, mssql, oracle, mongodb, cassandra, spanner, or dsql.
  2. Table names - comma-separated list of tables to generate (e.g. users, orders, products).
  3. Seed row counts - comma-separated count per table (e.g. 10000, 5000, 1000). Tables without a count default to 10000.
  4. Columns per table - for each table, enter name:type pairs comma-separated (e.g. id:uuid, email:text, age:int). Leave blank for defaults (id:uuid, name:text).

Supported column types#

TypeSQL Type (pgx)Expression
uuidUUIDuuid_v4()
textTEXTgen('name')
intINTuniform(1, 10000)
floatDOUBLE PRECISIONuniform(0.0, 100.0)
boolBOOLEANbool()
timestampTIMESTAMPTZtimestamp('2024-01-01T00:00:00Z', '2025-01-01T00:00:00Z')

SQL types are driver-aware. For example, uuid becomes CHAR(36) on MySQL and UNIQUEIDENTIFIER on MSSQL.

Generated Config#

The output includes all standard sections:

SectionPurpose
globalsPer-table row count and batch size
objectsColumn expressions for each table (SQL drivers only)
upCREATE TABLE statements (or MongoDB create commands)
seedBatch insert queries using __columns__ and __values__
initSELECT queries to fetch seeded data for ref_* access
runPoint read queries using ref_rand
deseedTRUNCATE statements
downDROP TABLE statements

Example#

edg scaffold > workload.yaml
# Select: pgx
# Tables: users, orders
# Row counts: 5000, 10000
# users columns: id:uuid, email:text
# orders columns: id:uuid, total:float

Produces:

globals:
  users_rows: 5000
  orders_rows: 10000
  batch_size: 1000

objects:
  users:
    id: uuid_v4()
    email: gen('name')
  orders:
    id: uuid_v4()
    total: uniform(0.0, 100.0)

up:
  - name: create_users
    query: |-
      CREATE TABLE IF NOT EXISTS users (
        id UUID,
        email TEXT
      )
  - name: create_orders
    query: |-
      CREATE TABLE IF NOT EXISTS orders (
        id UUID,
        total DOUBLE PRECISION
      )

seed:
  - name: seed_users
    count: users_rows
    size: batch_size
    object: users
    query: |-
      INSERT INTO users __columns__ __values__
  - name: seed_orders
    count: orders_rows
    size: batch_size
    object: orders
    query: |-
      INSERT INTO orders __columns__ __values__

init:
  - name: fetch_users
    query: |-
      SELECT * FROM users LIMIT 1000
  - name: fetch_orders
    query: |-
      SELECT * FROM orders LIMIT 1000

run:
  - name: read_users
    query: |-
      SELECT * FROM users WHERE id = ${ref_rand('fetch_users').id}
  - name: read_orders
    query: |-
      SELECT * FROM orders WHERE id = ${ref_rand('fetch_orders').id}

deseed:
  - name: clean_users
    query: |-
      TRUNCATE TABLE users
  - name: clean_orders
    query: |-
      TRUNCATE TABLE orders

down:
  - name: drop_users
    query: |-
      DROP TABLE IF EXISTS users
  - name: drop_orders
    query: |-
      DROP TABLE IF EXISTS orders

MongoDB#

When the mongodb driver is selected, the scaffold generates JSON commands instead of SQL and omits the objects section (MongoDB doesn’t use __columns__/__values__):

up:
  - name: create_orders
    query: |-
      {"create": "orders"}

seed:
  - name: seed_orders
    count: orders_rows
    size: batch_size
    object: orders
    query: |-
      {"insert": "orders", "documents": [{"id": $1, "total": $2}]}

Always validate generated configs before running them: edg validate config --config workload.yaml

Next Steps#

After generating a config:

  1. Review and customise - add foreign key relationships, transactions, run weights, or more complex expressions.
  2. Validate - run edg validate config --config workload.yaml to check for errors.
  3. Test - use edg repl --config workload.yaml to try expressions interactively.
  4. Run - execute edg up && edg seed && edg run against your database.