A guide that explains general ideas and patterns behind a multi-tenant system using Firestore, Security Rules and Cloud Functions.

The Firebase ecosystem offers quite a lot of advice on how to structure your data within Firestore — don’t normalize, use subcollections and so on. However, most of these tutorials only cover cases for scenarios where there are many independent users that create or change data. There is little advice on how to build a team-based system, where users are grouped into accounts or tenants.

In this article, I’m going to share the setup I thought of while building such a system. I will focus mainly on the general architecture and don’t go into too much detail of the implementation…

Humans seek a state of psychological consistency in which our mental attitudes and actions match up. How do we act when this is not the case?

How come so many people who smoke believe that life ends anyhow at some point, so why not enjoy it in the meantime?

Why do so many entrepreneurs with failed ventures argue that it was worth all the effort for the learnings?

And what is the reason so many divorced couples can only see the bad attitudes and habits in each other?

Image for post
Image for post
The couple, the entrepreneur and the smoker.

Cognitive Dissonance can provide an answer to these questions. First described in 1957 by Leon Festinger¹, Cognitive Dissonance is the uncomfortable feeling one experiences when two ideas one holds clash with each other — often a certain behaviour…

Asynchronous systems need to be able to notify their users about changes — which can be persisted as events and distributed through webhooks.

Firebase and Google Cloud Platform offer an excellent way to build apps and systems that can rapidly scale while providing a fantastic developer experience. At EstateSync, we use GCP services as the backend for our API to allow the fast distribution of real estate data to multiple vendors. Given the requirement to be able to scale to large amounts of data, we built our architecture on the premise of asynchronicity.

Because of this, there is an obvious need to keep users informed about what is going on within the system.

Image for post
Image for post
Don’t just wait until the events bite. (Photo by James Wheeler)

The Problem

Naturally in an asynchronous system, we can only provide the…

I recently read the book „The Subtle Art of Not Giving a F*ck“ by Mark Manson — these are my key learnings and thoughts from it.

A circle surrounded by tangled lines and stars that fall into a filter, reducing them to one single line.
A circle surrounded by tangled lines and stars that fall into a filter, reducing them to one single line.

Self-improvement culture: Better, Smarter, Happier

We live in a world that is strongly influenced by a high level of connectedness — to not turn mad, we need to filter out certain things. This filtering is often not done by ourselves, but rather (social) media, which is in turn motivated to supply us with the content most likely to satisfy our cravings. It creates a notion of needing to „be better, be happier, be smarter“ and a focus on what we might lack instead of what we already have.

On top of that, society promotes that negative feelings are not ok. By showing us only „feel…

„D“ stands for Dependency Inversion and promotes depending on abstractions rather than concrete implementations.

When developing new systems it’s usually easy to pay attention to creating modular structures and adhering to the Single Responsibility Principle. As a consequence, one often builds modules that take care of a specific task first and then uses them later in the business logic.

However, this often comes with a downside: These systems are usually tightly coupled because the business logic depends directly on the low-level module.

Image for post
Image for post
Don’t build gordian knot systems. (Photo by Douglas Bagg)

Dependency Inversion suggests changing („inverting“) this relationship. Instead of directly referencing the low-level module, one ought to reference its abstraction.

Let’s have a look at an example similar to the one of…

„I“ stands for Interface Segregation Principle and encourages only the implementation of behaviour that is actually required.

In software architecture interfaces are contracts that define no behaviour themself but that other modules must adhere to. They allow the consumer of a module to know how to talk to the module without having to know about details of it.

Image for post
Image for post
Use many small tools instead of one that claims to can do anything. (Photo by Todd Quackenbush)

A metaphor about interfaces

Interfaces are like an image you have in mind of the cashiers at a cinema. You know that you can tell them what movie you want to see and where you want to sit. You know that they are going to ask you for money and that you can give them money. Also, you expect them to hand you…

„L“ stands for Liskov Substitution Principle and encourages architectures that allow exchanging base classes for their subclasses without breaking things.

Inheritance is a powerful feature in software architecture, especially given the ability to override the behaviour of a base class. If you want to, you can extend a basic class and change its behaviour completely.

Image for post
Image for post
Inheritance is kind of like a Russian doll (Photo by Iza Gawrych).

This leads to the question of when inheritance should actually be used. Why not use composition instead? How do you know if you should implement a new feature by extending something that already exists and just modify its behaviour or by choosing a completely different pattern?

Barbara Liskov answered this question in a 1987 keynote and later formalized it in another paper in 1994:


„O“ stands for Open Closed Principle and promotes extension over modification.

Bertrand Meyer first brings up the “Open Closed Principle” in 1988 by writing the famous words

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

Image for post
Image for post
We don’t need to screw open our camera if we can just extend it with a new lens. (by Lucas Favre)

What that means is that there should be little need to modify existing code if we want to implement a new feature. At first, this seems a little contradictory because software changes all the time and so does its code, right? What about refactoring or even fixing bugs?

Let’s look at a concrete example to understand what the principle is trying to promote. The following example is written in…

S stands for „Single Responsibility“, which means to do only one thing, but do it well.

In software development the concept of building complex structures out of basic blocks is omnipresent, be it in the form of classes, components or modules.

According to the SOLID principles, each of these basic blocks should only have one job and defer additional jobs to other modules.

Image for post
Image for post
What shows up on Unsplash if you search „Focus“ (by Kyran Aldworth).

For example, let’s say one wants to react to an event that is thrown within an application. The event should be persisted to the database and a notification email should be sent to users. …

Laravel provides neat testing helpers for working with the filesystem –however if you run your tests in parallel, issues are inevitable.

Image for post
Image for post
Photo by Samuel Zeller on Unsplash


At Exposify we use the Storage Facade of Laravel to fluently access files and store data. It also makes writing feature tests much easier because it automatically swaps directories and cleans them up before running other tests with Storage::fake('my-disk').

We also use Paratest to let our PhpUnit Tests run much quicker by using multiple processes.

The thing is: As soon as you have multiple processes running, some tests will be executed before others are finished. This means that Laravel…

Richard Keil

Co-Founder at Exposify and EstateSync.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store