The first notion of multi-tenant applications started in the 1960s. You read that correctly, they are indeed that old. Companies would rent time, processing times and work time, on mainframes. In that time mainframes were expensive, individuals didn't own computers, and the idea that one day individual people would have more computing power in their hand than a mainframe was a wild dream. Thus this idea to share costs, share resources, and gain the advantages of a mainframe computer was born. The concept then was identified as time sharing.
Years went by and variations of this theme continued even amidst individuals starting to purchase computers, termed personal computers or as we still term them today, "PCs''. Even with these and other computer variants, time sharing continued as a prominent computing style for mainframes and supercomputers.
Then in the 1990s a new creation appeared that was termed application service providers, or ASPs. They hosted applications for their customers and similarly to mainframes, these applications were made available to multiple customers. This form was short lived but existed to serve and inform the next decade's revolutionary computing change that erupted with cloud computing. Which in many ways, cloud computing is effectively what ASPs had hoped to become, but the bandwidth and resources in that era's computing just wasn't up to the task.
Today, a solid decade plus worth of years into cloud computing we now have many different types of multi-tenancy based providers out there. Almost anything called something another -as-a-service is multi-tenant in some way. The cloud providers themselves are vast examples of multi-tenant services. Many companies you know; Salesforce, Google Docs, Office 365, Spotify, Slack, Steam, and other services are all multi-tenant.
Let's get pedantic now about multi-tenancy and pick apart some of the specifics.
There are many things that are termed multi-tenant that provide an element of what is needed to provide multi-tenant services but they aren't really multi-tenant themselves. For example, hyper-visor virtualization services are not multi-tenant. It's a tool that is regularly used to provide multi-tenant services but it is merely a tool. The same goes for the popular containerization tools such as Docker, it's a tool, and isn't particularly multi-tenant.
When talking about multi-tenancy one can often twist a single-tenant description into multi-tenancy and things can get confused. Single-tenant can mean a single tenant with a multi-tenant service or a singular tenant within a multi-tenant offering. Generally in a single-tenant environment we can think of each customer sharing software, servers, databases, or at least parts of the software, server, or databases. In a multi-tenant environment each customer would get their own software, services, or databases, however that line can get real muddied real fast!
For this section I’m going to break out a few options around using Hasura from several multi-tenant perspectives;
- Multi-tenancy by service/API.
- Multi-tenancy by schema & data.
- Multi-tenancy by database.
Each of these perspectives can be mixed with the other, to provide various abstractions and separations of data, services, and geographic location of compute or storage. All things that might physically be needed but also might be mandated for an architectural need from a legal perspective.
One possible way to break out services for different customers is to geographically locate the GraphQL API at the nearest geographic point of presence. Another situation might be a need for the access of API calls to occur within a particular state by legal requirement. In the latter situation one might spin up a Hasura API in AWS in the US-West region located in California. This would give California residents access to the API endpoint that is geographically located in their state, thus meeting the respective requirement.
The other possible solutions would be to split service by geographic location by customer location. An example of this situation might be that the point of access for a customer is the east coast, something detected when they spin up their instance, so the instance uses that automatically detected location and spins up the API in US-East.
Below is a sample Azure deployment where several databases from different virtual networks. These are accessed via a Hasura API service that connects from another virtual network. All of which could or would be geographically located or set up to provide tenancy that is separated between databases.
The summary of multi-tenancy through individual deployments of the Hasura API server instance can be brought into architectures in numerous ways, keeping them independent or bringing together multiple database servers altogether under a single instance. All of this together, to borrow a relational database term, is very much a many to many, one to many, or many to one relational architecture design.
One way that can provide multi-tenancy support within applications and systems, is to break out customer tenancy by schema and data design within the database itself. The key limitation with this model is limited geographic options to break out the data itself within a cloud provider or otherwise. However some of the benefits around this option is to manage tenancy through the application itself instead of systems deployments, and keeping the application aware of its own tenancy. This is in effect very much how tenancy is managed in the big web properties like Twitter, Facebook, and similar.
In this model one can take a schema per customer or use data to delineate different tenancy and break out queries and related assets based on the schema. This provides a hard differentiation to ensure no cross-over tenancy conflicts or the like. The following is a simple breakout for a schema that could be used to provide tenancy per customer while using a singular database. With additional authorization and other capabilities inherent in the Hasura server this provides a wide range of flexibility to provide customer tenancy per application just from the perspective of the data in a database.
The summary of schema and data design focuses around the various ways and limitations of the underlying database can be split by schema, the automation of said schema, and further breaking out elements to the actual data, segmentation and segregation of data in the system itself, and bringing those together to split according for each customer tenant.
The final form, which is another flexible multi-tenancy model, is to split customers, services, or other application collateral across databases. These could be databases in one region or multiple, split not just across geographic boundaries but also across groupings of customer class, rank, or other division. Some may even divide data among databases for sharding or gamification. The options are wide ranging.
The basic database division in Hasura is enabled by connecting multiple databases to a singular Hasura instance as shown below.
The following is an example of keeping tenants divided by data and schema usage in Postgres and Hasura. More concisely, an example of tenancy divisions by schema. In this example the tenants are broken out by schema within the database. As shown with tenant1 and tenant2 schemas.
To bridge the data across the schemas, to query against specific tenants, we would then create a view in the public schema. The create code, for copy and paste friendliness,would look like this.
CREATE OR REPLACE VIEW "public"."tenant_mps" AS SELECT 'tenant1' :: text AS tenant, mps.data, mps.date FROM tenant1.mps UNION ALL SELECT 'tenant2' :: text AS tenant, mps.data, mps.date FROM tenant2.mps;
Specifically, here is the same code in the console.
With that in place we would now see data, populated as shown, showing each of the tenants and providing access via a single query.
The advantage of this model is that we can now set up security authorization using Hasura across those tables, that this query would then automatically filter as per authorization rights.
There are multiple ways that multi-tenancy can be a feature need, from customer needing physical tenancy separation, to data just being cleanly available to one or another customer from an application use perspective. Whatever the case, GraphQL combined with Hasura provides a significant advantage in developing the tiers of an application (like Twitter or an ERP), or system of applications (like Google Docs) that need to have a multitude of databases federated together via an API.
We'd love to hear from you, about the systems you're building, or things you're interested in, from architecture to tactical deployments, join us on Discord and let's discuss!