synthtraffic Get started
Docs menu

Getting started

Overview

Synthtraffic generates production-shaped traffic from a YAML or JSON scenario. You describe the events you need, preview them safely, then send them to Kafka, PostgreSQL, HTTP, files, or cloud storage.

It runs on your machine: a CLI (sample, run, studio) and a local Studio. There is no hosted playground, and scenarios cannot contain JavaScript or custom functions. Commands need a license file that you request and keep locally.

This page is the product map, told as one marketplace story: products, customers, carts, related orders, changing order states, and events leaving for Kafka.

The core idea is simple: write the shape you want under value. Plain values are emitted exactly as written. Values beginning with = are expressions that Synthtraffic calculates. Values beginning with $ reuse a result that was already calculated.

value:
  product: Wireless headphones       # stays the same
  productId: =uuid()                 # a new id is calculated
  productUrl: =concat(/products/, $productId) # reuses that id

A generator repeats that value to create one stream of events. A scenario can contain several generators, and a connection can deliver their completed events to another system.

Press Try it on any example. It runs in the browser without installing Synthtraffic or contacting a real destination. To run a file on your machine, start with the Quickstart.

Shape an event

Start with the event your application expects. For a product listing, that might look like:

{"name":"Wireless headphones","store":"Amazen","productId":"<generated id>","productUrl":"/products/<same id>","stock":2}

The scenario keeps the product name and store fixed, calculates an id for every event, reuses that id in the URL, and counts stock upward.

A storefront listing

YAML shape.yaml
generators:
  - name: products
    const:
      store: Amazen
    vars:
      productId: =uuid()
    value:
      name: Wireless headphones
      store: $store
      productId: $productId
      productUrl: =concat(/products/, $productId)
      stock: =seq(start=2, step=2)

Press Try it. Compare the YAML with the output:

  • const.store is calculated once for the generator.
  • vars.productId is calculated for each event.
  • $store and $productId copy those results into value.
  • =seq(start=2, step=2) produces 2, 4, 6, and so on.

Generators explains streams and output shape. vars and const explains when reusable values are calculated.

Generate realistic data

Fixed placeholders are useful for structure, but production-like traffic also needs varied names, contact details, quantities, and prices:

{"customer":"<realistic name>","email":"<matching email>","quantity":"1 to 4","unitPrice":"48.50 to 89.90"}

faker() generates realistic-looking data. int() and float() keep numbers inside the ranges you choose.

A customer adds headphones to a cart

YAML realistic.yaml
generators:
  - name: carts
    vars:
      person: =faker(person)
    value:
      cartId: =uuid()
      customer: $person.fullName
      email: $person.email
      phone: =faker(phone.number)
      shipCity: =faker(address.city)
      product: Wireless headphones
      quantity: =int(1, 4)
      unitPrice: =float(48.5, 89.9, round=2)

Press Try it. The name and email come from one generated person, quantity stays between 1 and 4, and round=2 keeps the price at two decimal places.

This is still the same rule as the product example: the object keeps the shape written under value; expressions replace only the fields that should vary.

Control time and traffic

Events often need both realistic timestamps and controlled spacing. Here, cart events should begin at a known time and advance by 200ms:

09:00:00.000  →  09:00:00.200  →  09:00:00.400

The scenario clock supplies timestamps to now(). clock.start fixes the first timestamp, while interval moves the clock forward between events. A seed repeats random choices; a fixed clock repeats timestamps.

Carts on a fixed clock

YAML time-pace.yaml
defaults:
  seed: 42
  clock:
    start: 2026-03-01T09:00:00Z

generators:
  - name: carts
    config:
      interval: 200ms
    value:
      cartId: =uuid()
      product: Wireless headphones
      quantity: =int(1, 4)
      addedAt: =now()

Press Try it. addedAt begins at 09:00:00 and advances by 200ms on every cart event.

Time and pace explains scenario time, rate, interval, and stopping conditions.

Relate event streams

Independent random ids can create orders for customers who never existed. A useful relationship has a matching id in both streams:

{"customerId":"<generated id>","name":"<customer name>"}
{"orderId":"<generated id>","customerId":"<same customer id>","customerName":"<same customer name>"}

ref(customers) selects a customer event that Synthtraffic already generated. The order can then copy that customer’s id and name.

Customers first, then orders that point at them

YAML relate.yaml
generators:
  - name: customers
    config:
      maxEvents: 1
    value:
      customerId: =uuid()
      name: =faker(person.fullName)

  - name: orders
    config:
      maxEvents: 2
    vars:
      customer: =ref(customers)
    value:
      orderId: =uuid()
      customerId: $customer.customerId
      customerName: $customer.name
      product: Wireless headphones
      total: =uniform(12, 240, round=2)

Press Try it. Every order’s customerId and customerName match a customer shown earlier.

Relationships explains retained events, ref(), and when a schedule is needed.

Model entities over time

Some traffic describes updates to the same thing. One order should keep its id while its status changes:

<same order id>  PLACED
<same order id>  PACKED
<same order id>  OUT_FOR_DELIVERY

An instance keeps stable fields such as orderId. A state machine changes what that instance emits as it moves through its lifecycle.

One order changes status

YAML entities.yaml
generators:
  - name: orders
    config:
      maxEvents: 3
    instances:
      count: 1
      fields:
        orderId: =uuid()
    value:
      orderId: $orderId
      product: Wireless headphones
    stateMachine:
      initial: placed
      states:
        placed:
          emit:
            status: PLACED
          next: packed
        packed:
          emit:
            status: PACKED
          next: out
        out:
          emit:
            status: OUT_FOR_DELIVERY

Press Try it. The same orderId appears three times with three different statuses.

Instances teaches stable identities. Lifecycle teaches states and transitions.

Send events somewhere

When the event shape is ready, add destination details. Kafka needs an envelope containing a topic, optional key and headers, and the generated value:

{"topic":"amazen.orders","key":"<order id>","value":{"orderId":"<same order id>","product":"Wireless headphones"}}

The top-level connections block describes how to reach Kafka. connection: kafka selects it for the generator. topic, key, and value describe what Kafka receives.

Send the order to Kafka

YAML connections.yaml
connections:
  kafka:
    type: kafka
    brokers: [localhost:9092]

generators:
  - name: orders
    connection: kafka
    topic: amazen.orders
    vars:
      orderId: =uuid()
    key: $orderId
    value:
      orderId: $orderId
      product: Wireless headphones
      total: =uniform(12, 240, round=2)

Press Try it. It does not contact the broker; it safely shows the Kafka-shaped envelope in the browser.

Other destinations use different shapes: PostgreSQL uses a table and row, HTTP uses request fields and a body, and storage uses a prefix and value. Preview with sample or run --stdout before opening a real connection.

Where to go next

  • Quickstart — print three events on your machine
  • Scenario file — see where every major part belongs
  • Generators — start building a scenario, chapter by chapter
  • Connections — every destination in one place
  • sample and run — CLI reference when you already know the commands