Formats
SynthEvents writes a data set in one of two formats: as plain CloudEvents, or as a backup for EventSourcingDB. Both carry the same events and differ only in their envelope. You choose one with the format parameter of a request, cloudevents or eventsourcingdb.
What Both Formats Have in Common#
Both formats are NDJSON: one JSON object per line, each line ending with a newline. A data set is sent with the content type application/x-ndjson, and its file name ends with .cloudevents.ndjson or .eventsourcingdb.ndjson.
The events are written the way EventSourcingDB writes them, so that a data set looks like data that came out of it:
timeis in UTC, to the nanosecond, without trailing zeros, such as2025-01-01T00:00:00Zor2025-01-01T00:00:00.009892423Z. All events of one command share the same time.idcounts from0in the order the events happened, and time never runs backward.sourcenames SynthEvents and every parameter of the request except the format (see The Source as a Recipe).typeisio.synthevents.<domain>.<event>, such asio.synthevents.library.book-borrowed.datais in the normal form of EventSourcingDB: compact, with its keys in alphabetical order, and with<,>, and&escaped as\u003c,\u003e, and\u0026.
For the fields of a CloudEvent, see CloudEvents.
Plain CloudEvents#
With the format cloudevents, every line is one CloudEvent, with its fields in the order in which CloudEvents lists them, which is also the order in which the API v2 of EventSourcingDB writes an event when you read it: specversion, id, source, subject, type, time, datacontenttype, and data. There are no hash fields.
{"specversion":"1.0","id":"48","source":"tag:synthevents.io,2026:synthevents;version=golden;domain=library;scenario=everyday;from=2025-01-01T00:00:00Z;to=2026-01-01T00:00:00Z;eventCount=500;seed=golden","subject":"/books/dd9ceeee-febe-436b-9b66-17334b5a7abc","type":"io.synthevents.library.book-borrowed","time":"2025-01-01T17:12:14.331645957Z","datacontenttype":"application/json","data":{"borrowedAt":"2025-01-01T17:12:14.331Z","borrowedBy":"/readers/6e682d89-e9e9-4d55-8672-2da67f8bf38a","borrowedUntil":"2025-01-22"}}
Note that this event comes from a test of SynthEvents, which generates its data sets with the version golden and the seed golden. In a data set of the public service, version names the version of SynthEvents that generated it.
Use this format for anything other than EventSourcingDB: to read the events line by line, to import them into another system, or to process them with tools such as jq.
Backup for EventSourcingDB#
With the format eventsourcingdb, the data set is a backup of EventSourcingDB, ready to be restored into an empty instance. Like every backup, it has two kinds of lines, and its lines carry their content in payload:
- First, one
schemaline for every event type of the domain, in alphabetical order of their types, with the JSON schema of its data. After a restore, EventSourcingDB checks every event you write of one of these types against its schema. - Then, one
eventline for every event, with the event and itshash. The fields of the event are in the order of a backup:source,subject,type,specversion,id,time,datacontenttype,predecessorhash, anddata.
Shortened, a backup looks like this:
{"type":"schema","payload":{"eventType":"io.synthevents.library.book-acquired","schema":{...}}}
...
{"type":"event","payload":{"event":{"source":"...","subject":"/books/...","type":"io.synthevents.library.book-imported","specversion":"1.0","id":"0","time":"...","datacontenttype":"application/json","predecessorhash":"0000000000000000000000000000000000000000000000000000000000000000","data":{...}},"hash":"esdb:hash:v2:..."}}
{"type":"event","payload":{"event":{"source":"...","subject":"/books/...","type":"io.synthevents.library.book-imported","specversion":"1.0","id":"1","time":"...","datacontenttype":"application/json","predecessorhash":"esdb:hash:v2:...","data":{...}},"hash":"esdb:hash:v2:..."}}
...
The events form a hash chain: the predecessorhash of every event is the hash of the event before it, and the first event has 64 zeros instead. The hashes are of version 2, which starts every hash with esdb:hash:v2:. On a restore, EventSourcingDB computes every hash again and checks it.
If you restore a data set and then back the instance up again, the backup is the data set again, byte for byte.
EventSourcingDB 1.3 or Later
The hash of version 2 comes with EventSourcingDB 1.3, so a data set in this format needs version 1.3 or later. Earlier versions are not supported. Until version 1.3 is released, use the image thenativeweb/eventsourcingdb:preview.
To restore a data set, send it to the /api/v1/restore endpoint of EventSourcingDB:
curl \
-i \
-X POST \
-H "authorization: Bearer <API_TOKEN>" \
--data-binary "@backup.ndjson" \
http://localhost:3000/api/v1/restore
A restore only works on an empty database. For details, see Backup and Restore.
Choosing a Format#
- To load a data set into EventSourcingDB, choose
eventsourcingdb. A restore keeps the IDs, times, and hashes of the events, so the store holds them exactly as SynthEvents generated them, including the schemas of their event types. - For anything else, choose
cloudevents.