Creating an Inclusive Django Community with Kenya Phelps
Published July 15, 2026
This video features Brendan Wee at DjangoCon US 2021 in Online.
Multitenancy offers a cost-sensitive way to implement data segregation, data sharing, and least privileged access for multiple clients in an application. We present a new lightweight multitenancy approach that is compatible with any Django application, easy to implement, use, and maintain.
This talk was presented at: https://2021.djangocon.us/talks/lightweight-multi-tenant-architecture/
LINKS:
Follow Brendan Wee 👇
Website: https://www.secondgenome.com/
Follow DjangCon US 👇
https://twitter.com/djangocon
Follow DEFNA 👇
https://twitter.com/defnado
https://www.defna.org/
Video production by the speaker and DjangoCon US 2021 Volunteers.
Multi-tenancy lets one application serve multiple customers while keeping their permissions and data separate. Brendan Wee compares user–tenant relationships and three storage strategies—separate databases, a shared database and schema, and separate schemas—highlighting the trade-offs in isolation, cost, data sharing, query complexity, and operational overhead. He then shows how Django Guardian’s object-level permissions can turn Django groups into tenants in a shared-schema design: posts carry a tenant group, Guardian grants that group view permission, and permission-aware views expose only each user’s assigned posts plus shared data.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Hello, and welcome to my talk here at DjangoCon 2021. Today I will be presenting on lightweight multi-tenancy with Django Guardian. But first, a little bit about myself. I am a senior engineer at Second Genome. Second Genome is a tech-enabled precision therapeutics company harnessing the rich information of the human microbiome. Over here we leverage Django to maintain important clinical metadata on a microbial database of over 67,000 samples. Now, enough about me, let's talk about multi-tenancy. In today's talk, we will be going over the following points. What is multi-tenancy and why do we care about it? What are some strategies used when designing multi-tenant
architecture? What is Django Guardian? And How can we use Django Guardian to implement a multi-tenant architecture? Finally, we will wrap it all up with a demo to show just how to do that. So, what is multi-tenancy? A multi-tenant application is an application that has architecture allowing a single instance To serve multiple tenants. In other words, we host our application in a single place, and our customers can share the same resources. This architecture is opposed to the traditional architecture where Each tenant is hosted in their own dedicated instance, as shown on the right. Naturally, multi-tenancy is suited for applications that need to cater to several different clients.
yet still maintain separated permissions and access. Now, to help drive home the importance of multi-tenancy, here are some common benefits observed when software is adapted or created. To allow for multi-tenancy. It is usually easier to manage and update because whenever you have a change you need to push, it happens only in a single place. No longer would you have to jump between instances of the same application to deploy your change. It is typically cheaper to do so as well. because you do not have multiple instances to hosts. As opposed to the single tenant architecture, you would have a duplicate instance for each tenant. Lastly, it allows for easier sharing of data and services between customers.
Data does not need to be duplicated and can easily and efficiently be shared among clients. This is especially common for software as a service applications. If that wasn't enough to convince you, listen to this. Multitenancy is very common Odds are you already use multi-tenant software. Companies like Slack, Stack Exchange, Dropbox, and Discord all employ multi-tenant architecture, although in different ways. If you are a web developer, and I'm hazarding a guess you are, here at DjangoCon, you are going to encounter multi-tenant architecture, if you haven't already, at some point in your career.
So, we should probably get familiar with it. First, in order to understand multi-tenancy, we must get familiar with the concept of tenants. Tenants are a group of users with shared access and specific privileges to the software. For Slack, tenants take the form of workspaces. Stack Exchange has websites. Dropbox has clients. And Discord uses servers. Great. Now that we are familiar with the concept of tenants, we can begin discussing some of the different design decisions made in multi-tenant architectures. The first design decision we will talk about
is the relationship between users And tenants. This is an important decision a developer makes in how to model permissions and access It is unique to each application and ultimately up to you decide what makes sense and what works best. The first design we'll talk about is user is tenant. This is like how Gmail and Dropbox manages their users. The second is user within tenant. This is where users are restricted to a single tenant. Slack does this Lastly, we have user outside of tenant, where users and tenants have a loose relationship. Discord is a great example of this.
Let's talk a bit more about each. The first we'll talk about is user is tenant. Here, each user is assigned to a single tenant, and each tenant houses only a single user. Each user is given their own specific access and customized privileges In the case of Gmail, each user is given a personalized custom account and has access to their emails It does not make sense for multiple users to have access to the same email. A single user does not need access to multiple email accounts. The second design is user within
tenant. Here, users can only belong to a single tenant, but multiple users may exist in each tenant. Slack is our example application for this. Users cannot even log into Slack without first specifying the workspace they are logging into. Workspace, a workspace hosts multiple users who all have permission to message each other. And in this case, without multiple users to a workspace, the application is meaningless. You would just be talking to yourself. Or worse. The last design I call user outside of tenant. Here the relationship between tenant and user is very loose. Tenants can house multiple users, and users can belong to multiple tenants.
The application we chose to represent this is Discord. Where it is very easy for a user to jump between different servers and communicate with the other users inside each of those. They can do all of this without even having to log out. Great. Now that we have talked a bit about user-tenant relationships, it is time to discuss our second design decision This decision is on how we can model our architecture to employ multi-tenant architecture. Here we will be going over three high-level strategies. for how to design and manage multi-tenancy. The first is multiple databases, where we have isolated database instances. The second, we call
single database shared schema. This is the architecture we will be demoing today. The last is a single database architecture approach with multiple schemas. Let's talk about each of these a little bit more. The multiple database approach. In this architecture, each tenant has their own isolated database. This is great for isolation and security reasons. There is a very low chance of improper access Due to the physical separation of data. This separation is not something a developer has to actively manage or custom edit queries for. This design is naturally optimized for isolation.
However, as we continue to add more tenants, our prices will increase alongside of that. Each new tenant requires another database instance that needs to be paid for and managed Furthermore, if there is common data that needs to be shared between tenants, this data needs to be copied to each database instance in order for it to be available to all the tenants Next is the single database single schema approach. In this architecture Tenant specific data is marked by an identifier, commonly found in the form of a tenant column. In this design, shared data is not duplicated. Instead, access to it is managed by a tenant column.
Another benefit compared to the multiple database approach is that a single database instance means a lower operational cost. You do not have to create a new database instance for each tenant. However, there are cons as well. In this strategy, data segregation typically has to be handled manually. It is up to the developer to ensure that permissions are configured correctly. Data is annotated And queries are filtered by tenant. Lastly, because you have a shared database, that means that tenants can all use the same database resources. So if a tenant begins a costly operation on the database, the workload may become a hindrance to other tenants.
Our final strategy is the database single database multiple schema approach. In this approach, we maintain separate tenant-specific tables. However These tables can have the same name. Queries are then routed by a custom database to ensure That tenants access the data they are supposed to. This is great because since the tables are named the same name, Queries can remain unchanged, making it very simple to write and maintain queries. It is also pretty optimized for isolation, since the data is physically separated into different tables. However, there is an added complexity to this design, as it requires a custom database to route your queries to the appropriate.
table. This design requires you to make also requires you to make custom migrations and these custom migrations can take a long time as well. So after all this, you may be asking, well, which one is best? And the answer is none. As we've clearly shown, each user tenant design and each database schema design Has their own advantages and disadvantages. It is up to you to decide what is going to work best on your application. But for now, let's begin discussing object level permissions Injango Guardian A while back, Django
introduced the foundation for object-level permissions, but they did not provide an actual implementation. On this slide, you can see a snippet taken from the Django documentation itself. Luckily, this is where Django Guardian comes in. Django Guardian is a package that implements the object level permissions. In this basic use case, we can see we have a user Joe and we want to sign Joe permission to a specific group he is allowed to manage. However, we do not want Joe to be managed we want we do not want Joe to be able to manage all of the groups in our system. With Django Guardian, we can assign permission to Joe to change just the specific group we want him to manage.
Using Django Guardian, we can essentially turn user groups into tenants. Each user group naturally provides its grouping of users. And with Django Guardian, we can assign groups to provide customized permissions. on the same table. In some cases, this will help offload the work required to filter objects, as we can subset permission requirements on views and restrict access based on these permissions. So let me show you how to do it. I've prepared a demo for you all In this demo, we will be using Django Guardian with their example project, and we will make some very small modifications to show you just how easy it is to get started with a multi-tenant
architecture using Django Guardian. In this demo, we will be using the user outside of the tenant design because we want every tenant to have access to this shared data. And lastly, we must use the single database, single schema approach with Django Guardian. And this is because Django Guardian does not currently work with multiple databases to a bug. So, without further ado, here's the demo. Thank you In this demonstration, we will be using the Django Guardian example project. This is a project that Django Guardian provides to showcase some of the abilities of the package. The first thing we'll need to do is set up our environment.
We will clone the repo and go ahead and change into the directory. Here we will make our virtual environment. We can activate the environment, then install the required packages for the project. After installing the requirements, we will still need to install Django
Guardian. Once that's done, we can set up our database. And create a super user for that database. Great. Now let's take a look at this application.
This is a simple application that hosts two types of data, articles and posts. Now to turn this into a multi-tenant application, we will go ahead into the admin and log in. Once we're in here, we'll go ahead and create the groups. These are representing our tenants. We'll create two tenants, as well as a third for all the shared data that we'll have. Once we have the tenants, we can go ahead and add some users.
And add those users to the groups. Great. Now we are perfectly positioned to run a multi-tenant application. The next change we'll do is within the models and views themselves. Let's go ahead and open the project in an editor. For now, let's just worry about posts.
Under models, we'll need to import the groups that we're going to assign permissions to and overwrite the save function. We will be creating a tenant column for the post table, where we will assign the tenant to each post.
And we don't need to show this to users, so we can go ahead and exclude it from the view. Lastly, we'll overwrite the save function. In the save function, we want to go ahead and assign the permission
to view the post to the group. And we want to view this specific group that we're saving, or this post that we're saving. Great! Now that the model is done, we can also update the views. Guardian provides mix-ins for views that can restrict the views by permissions. Let's go ahead and add one to the post list When you provide the permission list mix-in, you also need to state which permission is required.
Here, we'll say that it is viewpost. Now that this is done, we can go ahead and make the migration. We can run the server again. And we're back on our site. Next thing to do is just add some posts.
This first post should be only available to tenant one. And when we log in as user two under tenant two, you should not be able to see it. The second post is for tenant two Lastly, let's add some shared data that everyone can see.
Great. Now all that's left is to see it in action. If we log in as user one in tenant one. We can see that the post for tenant two is hidden. We cannot see it. This user only has permission to the shared data and tenant one. If we log in as user two We see that this user also can only see the data that they've been assigned to based on their tenant group. And there you go.
With just a few simple modifications, we've adjusted this application to accommodate multiple tenants. This by no means is the definitive way to implement this package. As we've talked about before, there are many design decisions involved when creating or implementing this type of architecture So, if you are interested, I encourage you to go to the Django Guardian documentation and look at which specific modules and functions may benefit your application the most. That wraps it up for today. I would like to thank you all for your time, and I hope you all have a wonderful rest of your DjangoCon. Thank you.
It lets one application instance serve multiple customers while keeping their permissions and access separated. It generally makes updates and management easier, lowers hosting costs, and makes sharing data and services between customers more efficient.
Discussed at 1:16A user can be the only member of a tenant, belong to one tenant alongside other users, or have a loose relationship in which both users and tenants can be associated with multiple counterparts. The talk illustrates these patterns with Gmail/Dropbox, Slack, and Discord respectively.
Discussed at 4:25The choices are separate databases per tenant, one shared database and schema with tenant identifiers, or one database with separate schemas or tables per tenant. Separate databases provide strong isolation but cost more, a shared schema is cheaper but requires careful filtering and permission management, and multiple schemas preserve isolation while adding routing and migration complexity.
Discussed at 7:27There is no universally best option: each database and user-tenant design has different advantages and disadvantages. The appropriate choice depends on the application’s requirements.
Discussed at 10:51Django Guardian implements object-level permissions for Django. It lets you grant a user or group permission for a specific object without granting the same permission across every object of that type.
Discussed at 11:38User groups can represent tenants, with Guardian assigning each group permissions over particular objects. In the demo, each post receives a tenant group and its view permission, while a permission-based view mixin ensures users see only posts their tenant group is allowed to access, including shared posts.
Discussed at 12:26The demo uses a single database with a shared schema, because Django Guardian does not currently work with multiple databases due to a bug. Tenant-specific access is handled through groups, object permissions, and a tenant column rather than separate database instances.
Discussed at 13:14Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 14, 2026