Docs menu
Build a scenario
Scenario file Generators vars and const Time and pace Defaults Relationships Schedules Instances Lifecycle Collections Connections Delivery behaviorGetting 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
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.storeis calculated once for the generator.vars.productIdis calculated for each event.$storeand$productIdcopy those results intovalue.=seq(start=2, step=2)produces2,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
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
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
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
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
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