👫️ Multitenancy
Event Sourcery implements multitenancy by adding tenant id to all objects it stores.
By default, EventStore works in so-called default context, tenant-less.
Switching tenant
To switch context to specific tenant, one should call scoped_for_tenant
method:
Isolation rules
There are three rules regarding isolation:
- streams and events from default, tenant-less context are not visible in any tenant-aware context
- streams and events from another tenant are not visible when working with tenant-aware context
- streams and events from any tenant are not visible when working with tenant-less, default context
This table summarises visibility rules:
visible? | tenant-less | tenant A | tenant B |
---|---|---|---|
tenant-less | yes | no | no |
tenant A | no | yes | no |
tenant B | no | no | yes |
Multitenancy in other features
Outbox and subscriptions
Both Outbox and Subscriptions are meant to be used in a system context, for example to implement a projection of events onto a read model. However, you can always get tenant id when working with them.
On any Recorded instance there is an attribute called tenant_id
.
For events that were created in a default, tenant-less context, tenant_id
has value of event_sourcery.event_store.DEFAULT_TENANT
.
Value of this constant should not be relied upon and is considered an implementation details.
In all places where you wish to check if an event was created in a default context, you should use this constant:
from event_sourcery.event_store import DEFAULT_TENANT
...
for recorded_event in subscription:
if recorded_event is None:
break
elif recorded_event.tenant_id == DEFAULT_TENANT:
print(f"Got tenant-less event! {recorded_event}")
else:
...
Event Sourcing
In case of Event Sourcing, whenever you construct a Repository make sure you pass a scoped EventStore instance: