4
6 Comments

How do you handle multi tenancy?

Hi IH, today I come back with an other tech question. This time I would like to know how do you indie hackers handle multi tenancy in your saas projects?

  • Application level?
  • Shared DB seperate Schéma per tenant?
  • Single DB per Tenant?
  • Hybrid Shared DB plus Single DB?
  • Single deployment per tenant?

It would also be really nice if you could share any tools or technology Stack you use to achieve this

If you are interested in helping a fellow IH in his project. Please fill out my 3min survey https://zakardo.typeform.com/to/Gp82Uz

on October 23, 2019
  1. 3

    This is something that your pricing will dictate. If you are only charging $10 a month you certainly can't afford to be doing a deployment for each tenant. Now take the extreme opposite of an enterprise SaaS where you are charging 10k per month, heck yes you can do a single deployment per tenant.

    You also need to think about who your customers are. If they are enterprises in the medical field or other similar industries you may have to pass a compliance test. Giving each tenant their own database would make it way easier to pass these compliance tests.

    If it was me I'd do it at the application level. Unless my pricepoint is larger than $8,000 a month than I would do a single deployment per tenant.

  2. 1

    A good question to ask is what you mean by multi-tenancy, and if a "tenant" is equivalent to a user, a client organization, a team, or some other concept altogether. It's also useful, I suppose to ask about the nature of the app (B2B, B2B in a regulated industry, or B2C).

    I always implement data segregation at an application level. This affords me several advantages:

    • I don't need to worry about users within a tenant seeing/editing data they shouldn't- even if it's that tenant's own data.
    • I can always add additional separations later as needed (multiple instances; multiple servers).

    Going this route is more work, of course, because you need to think about how you will handle request authorization from the very beginning of the application architecture process. I would argue, however, that you should think about this from the beginning.

    For the app I'm completing how (https://practiceSQL.com - a Vue SPA with an API backend), I use username/password authentication to generate a secure-only, http-only cookie which contains a JWT. This JWT contains claims which reflect the user's roles (in obfuscated form). Then, on every API request, the user agent sends this cookie and the API endpoints first validate that it's a valid token (authentication), then validate that the token shows that the user has the appropriate rights needed for the specific endpoint (authorization- a combination of assigned role and rights to see/edit the specified data).

    1. 1

      I'm not entirly sure what you mean by application logic?

      Providing a token and user roles is good and well, but how do you ensure that only the tenant who owns the data can access it? Merly annotating each SQL query with an additional WHERE clause seems quite cumbersome and error prone.

      1. 1

        Much of the relevant key data for tenant-based logic is encoded in the token. For example, the token will have a reference to the user, so I'll write the program code to reference data from this token when writing a query that is executed during an API call. A "GET /projects" endpoint that lists projects for a given user might run this SQL: "SELECT * FROM project WHERE user_id=?" will be run with this logic:

        1. Does the token indicate that the user has rights to even invoke this endpoint? (the roles noted in the token answer this question). If no, 401. Is yes:
        2. Run the query using the identity of the user provided in the token.

        That way there is no special logic that needs to be applied to the query; the endpoint follows a standard authenticate/authorize/execute pattern.

        Perhaps this endpoint also needs to serve data to an administrator for a given user (perhaps to service a support request?). In that case, perhaps the endpoint will also accept a query parameter to identify a given user. In this case, though, I'll have some logic like this:

        • Is the user an administrator (based on roles in the token)? If so, use the user_id from the queryString.
        • Is the user not an administrator, or is there no user_id queryString parameter? then user the user_id in the token.

        Doing this, assuming that the token can be trusted, means that a given person cannot access data they don't have right to access. It also protects against stuffing (e.g.: guessing user IDs)

        This is by no means the only way to handle authorization but it is one that I've always found to be clear and understandable.

        1. 2

          Thanks for the answer. Hm, I don't think you're talking about a multi-tenant architecture. The process you describe describes user authorization.

          1. 1

            Perhaps, but it's an approach that I've used for apps which are meant to serve multiple organizations simultaneously where the data cannot be mixed between organizations but can be shared among users (based on roles) within a given organization.

            Thanks for the feedback!