Skip to main content

Implementation

This documentation gives you an insight into the structure of the ZITADEL database. The goal is to give you a rough overview, so you know where which data is stored and which database schemas and tables are used.

Event

The single source of truth of ZITADEL are the events that are stored in the eventstore. From these events all different kind of resources e.g Users, Projects, Applications, etc. can be computed.

An event has the following data:

AttributeDescriptionExample
idunique identifier of the event, this is generated by the databaseb6402a60-e4655-4cc0-904b-f5c6760c4406
aggregate_typethe type of the aggregate, an aggregate can be compared to a resource or an object. One aggregate contains multiple event typesuser
aggregate_idThe unique identifier of an aggregate, this is generated by ZITADEL and is a sonyflake id168096909691353697
aggregate_versionThe aggregate version shows in which version of the aggregate the event was created. This is needed to be able to compute correct objectsv1
event_typeThe type of the eventuser.human.added
event_sequenceThe event sequence is a sequence number that is incremented by one for each event on the instance. For technical reasons, a number can be omitted in some cases. This is needed so that the sequence of the events can be ensured.1234
previous_aggregate_sequenceThis number is the sequence of the event last created on this specific aggregate. E.g. Last user with specific aggregate_id1233
previous_aggregate_type_sequenceThis number is the sequence of the event last created on this aggregate. E.g Last User1230
creation_datetimestamp when the event was created2022-07-05 13:57:56.358774+00
editor_userThe editor user contains mostly an unique identifier of a user. And tells who did the request that led to this event. Sometimes this can also be a name of a system within ZITADEL.165460784409638965, NOTIFICATION, LOGIN
editor_serviceThe service defines which API was called when the event got created. If the event was created from the system itself this is empty.Admin-API
resource_ownerThe resource owner defines to which organization/resource_owner the event belongs. This is an id generated by ZITADEL as sonyflake id168051083313153168
instance_idZITADEL is capable of containing multiple ZITADEL instances withing the system. This id is the unique identifier of the Instance and is generated by ZITADEL as sonyflake id.165460784409737865

Schemas

SchemaDescriptionExamples
SystemThe system contains everything that is needed outside the ZITADEL instances.assets, encryption_key
EventstoreEventstore is the base of ZITADEL and is the single source of truth. All the events stored in the eventstore can be used to generate different projections.events, instance sequences, system wide unique constraints
ProjectionsThe projections contain all the computed objects which are used for reading requests.users, projects, etc
AuthThis contains projections which are used for the auth api. All projections in this schema should be moved to Projections soonusers, auth_request, etc.
AdminapiThis contains projections which are used for the admin api. All projections in this schema should be moved to Projections soonstyling
NotificationThis contains projections which are used for sending notification. All projections in this schema should be moved to Projections soonstyling

Projections

The projections in ZITADEL contain all the computed objects, that are used for the reading requests. It is possible that the projections are slightly behind the actual event and not all objects are up-to-date.

Pub-Sub

To keep the projections as up-to-date as possible, an internal pub-sub system is used. As soon as an event is written to the event store, it is sent to the projections that have subscribed to this aggregate.

Spooler

It is sometimes possible for technical reasons that not all events were sent to the projections. For this reason, a spooler runs in parallel, which checks every n minutes whether there are new events that have not yet been processed.

Current Sequence

To ensure that no events get missed when creating the Projections, ZITADEL stores the current sequence, that was processed. You can find the current sequence in the following tables:

  • projections.current_sequences
  • notification.current_sequences
  • auth.current_Sequences
  • adminapi.current_sequences

The current sequence is stored for each ZITADEL instance and table.

AttributeDescriptionExamples
projection_nameThe name of the projection for which the sequence is valid.projection.users
aggregate_typeThe aggregate type where the sequence was fromuser
current_sequenceThe sequence that was last processed1234
instance_idThe instance to which the event belongs165460784409737834
timestampTimestamp when the table was updated2022-07-05 13:57:59.454798+00

Failed Events

Sometimes an event cannot be processed correctly for some reason and an error occurs. The event is then tried to be processed n times. When a defined number of attempts have failed, the event is stored in the Failed Events Table and the next event is processed. This must be done so that the projection is not blocked and no further events are processed.

You can find the failed_events in the following tables:

  • projections.failed_events
  • notification.failed_events
  • auth.failed_events
  • adminapi.failed_events
AttributeDescriptionExamples
projection_nameThe name of the projection for which the failed event should have been processed.projection.users
failed_sequenceThe sequence of the event that failed1234
failure_countThe number of times the event was attempted to be processed. If the number is lower than the max. attempts the event could be processed, but not on the first attempt5
errorThe error message that occurred when the event could not be processedUser not found
instance_idThe instance to which the event belongs165460784409737834