Writing Schemas¶
Schemas are standard Avro .avsc files. The generator reads the schema and
produces records by resolving each field in declaration order.
Validate before generating
Run avro-datagen validate -s schema.avsc to catch structural issues,
wrong logical type base types, broken ref targets, and unknown hint
keys before you generate any data.
Minimal schema¶
{
"type": "record",
"name": "Event",
"fields": [
{ "name": "id", "type": { "type": "string", "logicalType": "uuid" } },
{ "name": "name", "type": "string" },
{ "name": "count", "type": "int" }
]
}
Without any hints, the generator uses type-based fallbacks:
| Avro type | Generated value |
|---|---|
string |
Random hex string |
int |
Random 0--10,000 |
long |
Random 0--1,000,000 |
double / float |
Random 0--10,000 (2 decimal places) |
boolean |
Random true/false |
null |
null |
Logical types¶
Avro logical types produce semantically meaningful values:
| Logical type | Avro base | Generated value |
|---|---|---|
uuid |
string |
RFC 4122 UUID |
timestamp-millis |
long |
Epoch milliseconds |
timestamp-micros |
long |
Epoch microseconds |
iso-timestamp |
string |
ISO 8601 string |
date |
int |
Days since epoch (random date in last ~5 years) |
time-millis |
int |
Milliseconds after midnight |
time-micros |
long |
Microseconds after midnight |
decimal |
bytes / fixed |
Decimal string respecting precision and scale |
All time-based types support range hints -- see the
arg.properties reference for date and time-of-day
ranges.
Field resolution order¶
Fields resolve top-to-bottom in declaration order. A field can reference
any field declared above it via ref, template, or rules.
{
"fields": [
{ "name": "category", "type": "string", "arg.properties": { "options": ["A", "B"] } },
{ "name": "label", "type": "string", "arg.properties": { "template": "Category: {category}" } }
]
}
label can reference category because category is declared first.
Resolution priority¶
For each field, the resolver checks (in order):
rulesinarg.properties-- conditional logic (first matching rule wins)refinarg.properties-- copy from another field (with type conversion)arg.propertieshints -- checked in this order:template,faker,options,pool,range,patterndefault-- Avro default value- Type fallback -- generate from Avro type / logicalType
The first match wins.
Union types (nullable fields)¶
For nullable unions, the generator produces null ~20% of the time by default.
Use null_probability in arg.properties to control this:
For unions with multiple non-null branches (e.g. ["null", "string", "int"]),
a non-null branch is chosen at random.
Nested records¶
Records can contain other records:
{
"name": "address",
"type": {
"type": "record",
"name": "Address",
"fields": [
{ "name": "street", "type": "string" },
{ "name": "city", "type": "string" }
]
}
}
Arrays¶
{
"name": "tags",
"type": { "type": "array", "items": "string" },
"arg.properties": {
"min_length": 1,
"max_length": 3,
"items": { "options": ["urgent", "review", "flagged"] }
}
}
See length hints for all supported
forms (min_length/max_length, length: {min, max}, or a fixed integer).
Cross-schema references¶
For parent-child relationships across schemas (e.g. orders referencing real
customer IDs), use the foreign_key hint
to pick values from another schema's output file.