Skip to content

Generating Sample Events

This guide shows how to fill EventSourcingDB with a realistic amount of sample events. So far, you have written a handful of events by hand. To see what working with a store that has a history feels like, you can generate a whole data set with SynthEvents and restore it into EventSourcingDB.

SynthEvents generates synthetic but realistic events for a few sample domains. One of them is a public library, modeled on the one you have built in this tutorial: a librarian acquires and withdraws books, and readers borrow, renew, and return them, sometimes late, and pay the fees that come with that.

Starting With an Empty Database

A data set is loaded with a restore, and a restore only works on an empty database. Since you have written events in the previous steps, start with a fresh instance first.

If you started EventSourcingDB with a temporary data directory (--data-directory-temporary), as described in Running EventSourcingDB, it is cleaned up on shutdown. Press Ctrl+C to shut EventSourcingDB down, and start it again with the same command. It then starts empty. Otherwise, start it with --data-directory pointing to a new, empty directory.

Fetching a Data Set

SynthEvents keeps ready-made data sets of every domain, which are the same for everyone. To fetch the one of the library with about 5,000 events, send an HTTP request using QUERY to the /api/v1/read-data-set endpoint of SynthEvents. QUERY is the HTTP method for a request that reads data, and curl sends it like any other:

curl \
  -X QUERY \
  -H "content-type: application/json" \
  -d '{
    "name": "library-everyday-medium",
    "format": "eventsourcingdb"
  }' \
  -o backup.ndjson \
  https://api.synthevents.io/api/v1/read-data-set

This fetches a year of everyday operation of the library, 2025, with about 5,000 events. The number is approximate, because SynthEvents simulates the library over the year rather than counting events out. Since the data set is ready-made, everyone who fetches it from the same version of SynthEvents gets the same events.

The format eventsourcingdb makes the data set a backup of EventSourcingDB, ready for a restore. Its events are named after SynthEvents, such as io.synthevents.library.book-acquired, rather than after EventSourcingDB, as the ones you wrote by hand are, so that a data set tells where it comes from. For the other domains and sizes, see the documentation of SynthEvents; its product page offers ready-made data sets to download as well.

Restoring the Data Set

To load the data set into EventSourcingDB, send it to the /api/v1/restore endpoint:

curl \
  -i \
  -X POST \
  -H "authorization: Bearer <API_TOKEN>" \
  --data-binary "@backup.ndjson" \
  http://localhost:3000/api/v1/restore

If everything worked as expected, the server will respond with HTTP status code 200 OK:

HTTP/1.1 200 OK

If Something Goes Wrong

If the server responds with 409 Conflict, the database is not empty. Start with a fresh instance, as described above, and run the restore again.

For more details on the restore process, see Backup and Restore.

Exploring the Data Set

Now the database holds a year of a library. To get an overview, list the event types, as in Listing Event Types:

curl \
  -i \
  -X POST \
  -H "authorization: Bearer <API_TOKEN>" \
  http://localhost:3000/api/v1/read-event-types

You will find event types for the whole life of a book in the library, from io.synthevents.library.book-acquired and io.synthevents.library.book-borrowed to io.synthevents.library.book-returned, io.synthevents.library.loan-renewed, and io.synthevents.library.late-fee-issued. The stock the library had before the year began is there too, as io.synthevents.library.book-imported.

Each event type comes with its schema, because the data set brings the schemas of its event types along. From now on, EventSourcingDB checks every event you write of one of these types against its schema, as described in Registering Event Schemas.

Every book is a subject of its own, such as /books/<uuid>, and readers appear in the data of the events, such as in borrowedBy. Try the queries from Running EventQL Queries on this data set, with io.synthevents in place of io.eventsourcingdb in their event types and a subject of the data set in place of /books/42, and see how they behave on a store with a history.