Microservice Architectures — Single Tenant or Multi-Tenant?
I have been studying up on, working with, and implementing microservice architectures (MSA) for the last few years. One thing that struck me the other day is that I work with the microservices in MSAs as if they are loosely coupled and can be formed to work cohesively. Ok that works.
However, in my brain at least, each microservice is on its own with that application architecture. If I reuse a microservice (i.e. logging) in another MSA, it is a copy or clone of the microservice (usually a container) inside that MSA. It is not a single microservice shared out with multiple applications.
That is not the only way to think of MSAs, though. Where can I use a microservice in a multi-tenant way? Where could I? When would I be allowed to? And why would I? This article talks on some of those questions and a few examples and answers.
This is not a definitive “do this when X” kind of article. There are always multiple ways to do something in software development with valid pros and cons. This article is to get you thinking and asking the right questions when designing your MSAs for you and your team.
Single Tenant. Multi-tenant. What is the difference?
When I explain this whole “tenant” application thing to people, I use what they are familiar with. A single tenant is a single family house detached from others. Only one family uses it. A multi-tenant application or service is more like a condo building or apartment building. There are multiple people sharing the building, the water pipes, the drains, the roof, etc. Regardless of what they pay for, they are using shared infrastructure for their housing.
In terms of applications and microservices in particular, single tenant in this article means this microservice is only used by one application architecture. If its purpose can be used elsewhere, a new copy is made and run for that application setup. See the image just below for a visual of this. The logging, auditing, user profile, and geo mapping services can be used by multiple applications. Great.
Now to use them, that application setup runs a copy of the service, injects its configuration and environment variables, and runs it with other microservices to perform the application objectives. If another application can use it, they get their own copy. Those separate copies never talk to each other. And if they need to be replicated to handle more traffic, they do so independently from each other. They are in essence independent clones.
Multi-tenant is more like the image in the next section. You can have the logging, geo maps, user profile, and auditing setup to handle multiple applications with a single instance. That one instance knows what application is connecting to it to do the work and adjusts accordingly for that application.
If this service would need to replicate it would do so and every application that connects to it would benefit from more copies and resources being available. Any new application that wanted to use it would need to have whatever configuration inside the microservice adjusted for it to talk to and use that application, if required. Then it just uses the shared microservice with the other applications.
Why would you use Multi-Tenant?
So the question comes up then, why use one over the other? There are a few reasons I can think of where you may choose a multi-tenant microservice in your architecture. One big one is resources. If you choose a single instance every time your microservice runs, you are duplicating resources (CPU, memory, cost) required to run your microservice. And if you have a separate database or database table, that is also duplicated. Anything that microservice uses to run is duplicated. So if you need to conserve any of those resources, you may want to use a multi-tenant design.
You may also decide to use a multi-tenant design if you want to track the fewest instances of the microservice for CI/CD, updates, security, and the like. The decision could very well just be a people resources thing and tracking your software components.
In the case of logging, you may eventually pull all logs together anyway in a separate process. Imagine how easy that would be to scan logs if they were all in one place. You may be able to do it near real time easier as well. So that could be another reason to go multi-tenant.
These are just a few examples to get your brain thinking. You may have already thought of other reasons why you would design your microservices like this. Feel free to put additional ideas or examples into the comments to share your thoughts and ideas. I would like to hear them.
Where might you use Multi-Tenant?
I mentioned earlier, one place you may want to use multi-tenant could be logging. A similar place could be auditing. Put all your events into one spot and segment them inside the microservice/database by application. You can allow multiple tenants to use the system, and design the CRUD methods based on the application. You also can correlate information and view data across multiple applications all at one spot easier.
You also may have a set of logic in your microservice that is generic enough to be used in several places. Your code never saves any data in its processing. It just chomps on the data and runs logic on it then returns an answer. Yes, you could make this into a “function” that only spins up to answer the request (think OpenFaaS or AWS Lambda). However, if this is designed as a microservice and it has no sensitivity or data persisted, you could design it as multi-tenant easily.
Some examples: Maybe it is a GIS function to turn latitude and longitude into MGRS. Or a currency conversion service. Or a sales tax calculation service. There may be a few of these you have run across in your software engineering past that could be shared across applications with a single instance fairly easily (or cluster of replica instances for performance).
There are more than just these examples above. As I said above, you may have thought of some already and jotted them down. These ideas may also come up later when you are working on your development project or your side project at your house. Again, this is just to get the thoughts out there so you can have them in your mind and in your development toolbox when talking software architecture and design.
Where would you choose a Single Tenant approach?
On the flip side, there may be some very good reasons to choose a single tenant microservice architecture approach. Your design may segment your customers into their own clusters of servers for your MSA and they pay on the usage. It is easier to track and justify all costs if they are the only users of them in that particular design.
Your data and its sensitivity may be enough to warrant you, your company, or your eventual customer to require a separate service and separate database. That way any leaked data because of a bug or cybersecurity attack is only localized to that particular application. Your industry may also dictate best practice of this possibly, and you need to know that as well. That influences your application architecture.
Another reason could very well be that it is harder to do multi-tenant and test against it than to do single tenant. Single tenant is easier to think of in your mind, in your design, in your testing, and in your project scheduling and cost. Your team’s experience in doing multi-tenant or lack thereof may also influence you heavily in one way or the other. Just because a design may look beautiful does not mean it is realistic to do or go after based on time, cost, and personnel.
A final reason I will add deals with complexity. I love the K.I.S.S. method. Keep things simple. Making sure you design multi-tenancy so it keeps peoples information secured only to the correct application adds complexity. I know personally I design microservices so you can have different configurations and environment variables to spin up and connect to different resources. That is about as far as I go, so they are flexible and can connect to a different database, identity provider or messaging service. Doing multi-tenancy on top of that will add complexity and that may be a reason to stick to a single tenant approach.
What are some of the design choices to discuss?
There are probably some questions, concerns, ideas and such floating through your head now if you are a developer, architect, or system administrator. There are probably a lot more if you are like my buddy Dave at Tutela who is a Cybersecurity and Information Security guru. I listed out a few below.
This is not an exhaustive list. Again, this is to get you thinking and communicating across your integrated team on design choices and their pros and cons with your customer, your solutions, your environment, your constraints, and your data sensitivity.
Sensitivity of Data. If your data is sensitive, secure, confidential, is restricted by PCI DSS or HIPAA requirements, then you may want to have any microservice that has its own database to be a separate microservice that is single tenant. Just so it reduces the risk of data leaking. And it may be required by your industry, your customer, or your company for this reason. People may feel better about a design if the data is separate and are willing to pay for it, whether you think that is 100% valid or not.
Unknown Resource Usage. You should know the structure around the CPU, memory, network, database space, etc. your application requires. If not, you may not want to share microservices and resources. A bad design in one of the application tenants could impact every single application using that shared microservice.
Are you Allowed to? You also need to discuss if your customer or industry regulations allow you to do this. I mentioned this above. For instance in DoD realms where I live and work, you may be required to reuse code but use it in a separate area with a separate database and security scope. Can you share functions, and can you share databases if the microservice requires persisting data. Or will your design need to change if you share the microservice.
Do you have the time and team to do so. Designing, developing, and testing a multi-tenant microservice is harder for sure. You have to make sure your microservice does its functions, and does so only on the data it is allowed to see for the application that is calling it. Your design is a little harder. Your testing more thorough. And your security a lot more stringent around this concept. Changes to your codebase have to be tested against any and all applications using your service now or in the future. And your team needs to understand this before you go down this path.
Cost of duplication. If you run only single tenant microservices, and you are reusing services from them (hopefully you can) then you are duplicating the usage, CPU, memory, database space, and any persistent volume setup (if running something like Kubernetes) each time. The cost may increase quite a bit depending on the setup required and if you took the time to use minimal CPU and space to design your application architecture (because we all are allowed to do that in our projects, right!).
Where to go from here
I said from the outset my goal in this article is to get you and your team thinking on these things. And it is for me to write down while I have it in my head so I can revisit it later. I have used and reused my own posts time and time again to remind me what I did. Or to point out to others possibilities on doing their software engineering work. I just did this with an intern that had questions on Prometheus and Grafana. So yes, these are a little self serving . . . not going to apologize for that! :-)
There are some great articles below that I go back to time and again when I am working with MSAs. I am including them here for your review. If I had a suggestion to give, I would say try a few ways of doing this yourself in smaller designs and see how they work for you and your group. Test drive them. Get ideas in code and tested with working examples. That may help you later in your designs and testing.
The Hardest Part About Microservices: Your Data
Continuing on with my series about microservices implementations (see "Why Microservices Should Be Event Driven"…
It's common for software systems to make remote calls to software running in different processes, probably on different…
Microservices Pattern: Microservice Architecture pattern
You are developing a server-side enterprise application. It must support a variety of different clients including…