Hierarchical multi-tenant architecture with Django and Postgresql using separate schemas









up vote
3
down vote

favorite












I have a django app has clients and multiple users that are linked to those clients, and I want to migrate the system to hierarchical multi-tenant architecture.



Hierarchical Part



Clients can include other clients recursively. For instance, Client A includes Client B and Client C. If a user Client A logs in the system, user will see Client B and Client C's data. If a user of Client B logs in the system, user will see only Client B's data.



Multi-Tenant Part



I want to store all clients' data in separate schemas. But there is some data that is not relevant to clients, so I want to store that data in "public" schema.



When I research Building Multi Tenant Applications with Django, I saw this part:



def set_tenant_schema_for_request(request):
schema = tenant_schema_from_request(request)
with connection.cursor() as cursor:
cursor.execute(f"SET search_path to schema")


However, to apply my hierarchical example that I've mentioned above, I must reach multiple schemas at the same time. Can I do that or are there any other ways to implement my architecture?










share|improve this question



























    up vote
    3
    down vote

    favorite












    I have a django app has clients and multiple users that are linked to those clients, and I want to migrate the system to hierarchical multi-tenant architecture.



    Hierarchical Part



    Clients can include other clients recursively. For instance, Client A includes Client B and Client C. If a user Client A logs in the system, user will see Client B and Client C's data. If a user of Client B logs in the system, user will see only Client B's data.



    Multi-Tenant Part



    I want to store all clients' data in separate schemas. But there is some data that is not relevant to clients, so I want to store that data in "public" schema.



    When I research Building Multi Tenant Applications with Django, I saw this part:



    def set_tenant_schema_for_request(request):
    schema = tenant_schema_from_request(request)
    with connection.cursor() as cursor:
    cursor.execute(f"SET search_path to schema")


    However, to apply my hierarchical example that I've mentioned above, I must reach multiple schemas at the same time. Can I do that or are there any other ways to implement my architecture?










    share|improve this question

























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I have a django app has clients and multiple users that are linked to those clients, and I want to migrate the system to hierarchical multi-tenant architecture.



      Hierarchical Part



      Clients can include other clients recursively. For instance, Client A includes Client B and Client C. If a user Client A logs in the system, user will see Client B and Client C's data. If a user of Client B logs in the system, user will see only Client B's data.



      Multi-Tenant Part



      I want to store all clients' data in separate schemas. But there is some data that is not relevant to clients, so I want to store that data in "public" schema.



      When I research Building Multi Tenant Applications with Django, I saw this part:



      def set_tenant_schema_for_request(request):
      schema = tenant_schema_from_request(request)
      with connection.cursor() as cursor:
      cursor.execute(f"SET search_path to schema")


      However, to apply my hierarchical example that I've mentioned above, I must reach multiple schemas at the same time. Can I do that or are there any other ways to implement my architecture?










      share|improve this question















      I have a django app has clients and multiple users that are linked to those clients, and I want to migrate the system to hierarchical multi-tenant architecture.



      Hierarchical Part



      Clients can include other clients recursively. For instance, Client A includes Client B and Client C. If a user Client A logs in the system, user will see Client B and Client C's data. If a user of Client B logs in the system, user will see only Client B's data.



      Multi-Tenant Part



      I want to store all clients' data in separate schemas. But there is some data that is not relevant to clients, so I want to store that data in "public" schema.



      When I research Building Multi Tenant Applications with Django, I saw this part:



      def set_tenant_schema_for_request(request):
      schema = tenant_schema_from_request(request)
      with connection.cursor() as cursor:
      cursor.execute(f"SET search_path to schema")


      However, to apply my hierarchical example that I've mentioned above, I must reach multiple schemas at the same time. Can I do that or are there any other ways to implement my architecture?







      django postgresql database-design architecture multi-tenant






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 8 at 12:21

























      asked Nov 8 at 11:29









      goktugbc

      347




      347






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          You can list multiple schemas in the PostgreSQL search path. If the same table appears in several schemas only rows from the first schema in the search path will be returned. There's no automatic combining of rows from tables in different schemas. So that's probably not what you want.



          You could rearchitect your application so that every query selects data from tables in different schemas and then use union clauses to join those results together. While that would provide the right results, it should be clear that structuring all of your queries this way will complicate the application greatly and makes it also not a good plan.



          If you want the ability to see the data from several clients at once, a multi-tenant architecture with isolated schemas is not the right way to go. Having eliminated the alternatives, I think only one approach remains. You have to use shared schema multi-tenancy with rows from different clients in the same tables.



          Having a shared schema means that there's less separation of data from different clients, but it provides a simple way to show data from multiple clients at once in cases where that's what's required. The normal approach to implementation is to add terms to the where clauses of your queries to ensure that only data that should be visible for the logged-in user is returned.



          Another possibility you might consider would be to use row-level security within the database. With that approach each client would have their own Postgres user account with a policy that restricts access to only the rows that are applicable to them. That pushes some responsibility for ensuring correct security from the application layer to the database layer, which has pros and cons. A benefit is that security needs to be implemented only once at the database, as opposed to throughout the data access parts of the application. A possible drawback is that it may be more work for the database to do.



          https://www.postgresql.org/docs/11/ddl-rowsecurity.html






          share|improve this answer




















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206853%2fhierarchical-multi-tenant-architecture-with-django-and-postgresql-using-separate%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            You can list multiple schemas in the PostgreSQL search path. If the same table appears in several schemas only rows from the first schema in the search path will be returned. There's no automatic combining of rows from tables in different schemas. So that's probably not what you want.



            You could rearchitect your application so that every query selects data from tables in different schemas and then use union clauses to join those results together. While that would provide the right results, it should be clear that structuring all of your queries this way will complicate the application greatly and makes it also not a good plan.



            If you want the ability to see the data from several clients at once, a multi-tenant architecture with isolated schemas is not the right way to go. Having eliminated the alternatives, I think only one approach remains. You have to use shared schema multi-tenancy with rows from different clients in the same tables.



            Having a shared schema means that there's less separation of data from different clients, but it provides a simple way to show data from multiple clients at once in cases where that's what's required. The normal approach to implementation is to add terms to the where clauses of your queries to ensure that only data that should be visible for the logged-in user is returned.



            Another possibility you might consider would be to use row-level security within the database. With that approach each client would have their own Postgres user account with a policy that restricts access to only the rows that are applicable to them. That pushes some responsibility for ensuring correct security from the application layer to the database layer, which has pros and cons. A benefit is that security needs to be implemented only once at the database, as opposed to throughout the data access parts of the application. A possible drawback is that it may be more work for the database to do.



            https://www.postgresql.org/docs/11/ddl-rowsecurity.html






            share|improve this answer
























              up vote
              1
              down vote



              accepted










              You can list multiple schemas in the PostgreSQL search path. If the same table appears in several schemas only rows from the first schema in the search path will be returned. There's no automatic combining of rows from tables in different schemas. So that's probably not what you want.



              You could rearchitect your application so that every query selects data from tables in different schemas and then use union clauses to join those results together. While that would provide the right results, it should be clear that structuring all of your queries this way will complicate the application greatly and makes it also not a good plan.



              If you want the ability to see the data from several clients at once, a multi-tenant architecture with isolated schemas is not the right way to go. Having eliminated the alternatives, I think only one approach remains. You have to use shared schema multi-tenancy with rows from different clients in the same tables.



              Having a shared schema means that there's less separation of data from different clients, but it provides a simple way to show data from multiple clients at once in cases where that's what's required. The normal approach to implementation is to add terms to the where clauses of your queries to ensure that only data that should be visible for the logged-in user is returned.



              Another possibility you might consider would be to use row-level security within the database. With that approach each client would have their own Postgres user account with a policy that restricts access to only the rows that are applicable to them. That pushes some responsibility for ensuring correct security from the application layer to the database layer, which has pros and cons. A benefit is that security needs to be implemented only once at the database, as opposed to throughout the data access parts of the application. A possible drawback is that it may be more work for the database to do.



              https://www.postgresql.org/docs/11/ddl-rowsecurity.html






              share|improve this answer






















                up vote
                1
                down vote



                accepted







                up vote
                1
                down vote



                accepted






                You can list multiple schemas in the PostgreSQL search path. If the same table appears in several schemas only rows from the first schema in the search path will be returned. There's no automatic combining of rows from tables in different schemas. So that's probably not what you want.



                You could rearchitect your application so that every query selects data from tables in different schemas and then use union clauses to join those results together. While that would provide the right results, it should be clear that structuring all of your queries this way will complicate the application greatly and makes it also not a good plan.



                If you want the ability to see the data from several clients at once, a multi-tenant architecture with isolated schemas is not the right way to go. Having eliminated the alternatives, I think only one approach remains. You have to use shared schema multi-tenancy with rows from different clients in the same tables.



                Having a shared schema means that there's less separation of data from different clients, but it provides a simple way to show data from multiple clients at once in cases where that's what's required. The normal approach to implementation is to add terms to the where clauses of your queries to ensure that only data that should be visible for the logged-in user is returned.



                Another possibility you might consider would be to use row-level security within the database. With that approach each client would have their own Postgres user account with a policy that restricts access to only the rows that are applicable to them. That pushes some responsibility for ensuring correct security from the application layer to the database layer, which has pros and cons. A benefit is that security needs to be implemented only once at the database, as opposed to throughout the data access parts of the application. A possible drawback is that it may be more work for the database to do.



                https://www.postgresql.org/docs/11/ddl-rowsecurity.html






                share|improve this answer












                You can list multiple schemas in the PostgreSQL search path. If the same table appears in several schemas only rows from the first schema in the search path will be returned. There's no automatic combining of rows from tables in different schemas. So that's probably not what you want.



                You could rearchitect your application so that every query selects data from tables in different schemas and then use union clauses to join those results together. While that would provide the right results, it should be clear that structuring all of your queries this way will complicate the application greatly and makes it also not a good plan.



                If you want the ability to see the data from several clients at once, a multi-tenant architecture with isolated schemas is not the right way to go. Having eliminated the alternatives, I think only one approach remains. You have to use shared schema multi-tenancy with rows from different clients in the same tables.



                Having a shared schema means that there's less separation of data from different clients, but it provides a simple way to show data from multiple clients at once in cases where that's what's required. The normal approach to implementation is to add terms to the where clauses of your queries to ensure that only data that should be visible for the logged-in user is returned.



                Another possibility you might consider would be to use row-level security within the database. With that approach each client would have their own Postgres user account with a policy that restricts access to only the rows that are applicable to them. That pushes some responsibility for ensuring correct security from the application layer to the database layer, which has pros and cons. A benefit is that security needs to be implemented only once at the database, as opposed to throughout the data access parts of the application. A possible drawback is that it may be more work for the database to do.



                https://www.postgresql.org/docs/11/ddl-rowsecurity.html







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 9 at 3:32









                Oliver Crow

                456




                456



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206853%2fhierarchical-multi-tenant-architecture-with-django-and-postgresql-using-separate%23new-answer', 'question_page');

                    );

                    Post as a guest














































































                    Popular posts from this blog

                    𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                    Edmonton

                    Crossroads (UK TV series)