[{"data":1,"prerenderedAt":136},["ShallowReactive",2],{"i-lucide:menu":3,"i-lucide:arrow-up-right":8,"i-lucide:moon":10,"i-lucide:sun":12,"i-lucide:rss":14,"i-simple-icons:github":16,"i-simple-icons:linkedin":18,"post-\u002F2012\u002Fdesigning-a-database-for-multiple-clients":21,"surround-\u002F2012\u002Fdesigning-a-database-for-multiple-clients":123,"i-lucide:arrow-left":132,"i-lucide:arrow-right":134},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 7h10v10M7 17L17 7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16\"\u002F>\u003Ccircle cx=\"5\" cy=\"19\" r=\"1\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":17},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":19,"hidden":20},"\u003Cpath fill=\"currentColor\" d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037c-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85c3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.06 2.06 0 0 1-2.063-2.065a2.064 2.064 0 1 1 2.063 2.065m1.782 13.019H3.555V9h3.564zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z\"\u002F>",true,{"id":22,"title":23,"body":24,"category":106,"comments":107,"date":108,"description":30,"excerpt":107,"extension":109,"image":107,"meta":110,"navigation":20,"path":111,"readingTime":112,"seo":113,"stem":114,"subtitle":107,"tags":115,"wordCount":121,"__hash__":122},"posts\u002F2012\u002Fdesigning-a-database-for-multiple-clients.md","Designing a database for multiple clients",{"type":25,"value":26,"toc":98},"minimark",[27,31,34,39,59,62,66,73,76,80,83,87,90],[28,29,30],"p",{},"I've had several projects where one codebase & database needed to serve multiple clients. Another assignment with similar requirements is upcoming soon so this is a good time to reflect on some design strategies.",[28,32,33],{},"There are at least three distinct ways to design a database that ought to hold information for several clients.",[35,36,38],"h2",{"id":37},"separate-databases","Separate databases",[28,40,41,42,46,47,50,51,54,55,58],{},"This was my first approach, on my first project. The idea was that all clients run the same code, but the database in use gets decided dynamically by the domain name. So, ",[43,44,45],"code",{},"www.xxx.ee"," would use the database ",[43,48,49],{},"project_xxx_ee"," and ",[43,52,53],{},"www.yyy.ee"," would get ",[43,56,57],{},"project_yyy_ee",". The schema of those databases would be identical and their number unlimited. The approach worked and for a while everyone were happy.",[28,60,61],{},"The problem with this design is maintainability. Since the project I used this in was developed incrementally there was need for frequent database changes. Making a minor change required doing the same in all databases, manually. I didn't have any tools to do this so the solution was to do it by hand in PMA.",[35,63,65],{"id":64},"one-database-with-client_id","One database with client_id",[28,67,68,69,72],{},"Another way of holding data for multiple clients is to do it all in one database, but bind each row with ",[43,70,71],{},"client_id",". The data for all clients is stored in the same table, but always references to the owner, ie client with a foreign key. It's easy in InnoDB.",[28,74,75],{},"Such approach offers easier maintainability (you only need to make some schema change in one table), but the drawback is data portability and encapsulation. Say you wanted to extract all the data for one client - you can't, at least not with a traditional SQL export... and if your code has security bugs the data of another client might be displayed, modified or even deleted.",[35,77,79],{"id":78},"the-wordpress-approach","The Wordpress approach",[28,81,82],{},"Wordpress does a mixed approach: there's only one database, but each site in your network gets it's own table. You can dump the data of a client easily, privacy breaches are migrated better, but there's still the problem of maintainability, namely you'd need a tool to apply a database modification in all the tables after the system has been running for a while.",[35,84,86],{"id":85},"the-best-solution","The best solution?",[28,88,89],{},"It's difficult to say which strategy would be the wisest or if the 'right' choice is even listed here. My current method is to bind everything with a user or client and it seems to work quite well. What's certain is that I need to get my hands on a well-written database design book and learn more.",[28,91,92,93],{},"Update: Read this - ",[94,95,97],"a",{"href":96},"http:\u002F\u002Fwww.brentozar.com\u002Farchive\u002F2011\u002F06\u002Fhow-design-multiclient-databases\u002F","How To Design Multi-Client Databases",{"title":99,"searchDepth":100,"depth":100,"links":101},"",2,[102,103,104,105],{"id":37,"depth":100,"text":38},{"id":64,"depth":100,"text":65},{"id":78,"depth":100,"text":79},{"id":85,"depth":100,"text":86},"Software Development",null,"2012-05-30","md",{},"\u002F2012\u002Fdesigning-a-database-for-multiple-clients","about 2 minutes",{"title":23,"description":30},"2012\u002Fdesigning-a-database-for-multiple-clients",[116,117,118,119,120],"design","database","database design","erd","architecture",429,"sLbc7LpbURp18SMgijfmGaujA-FH8mKeY-ifTbSC5tE",[124,128],{"title":125,"path":126,"stem":127,"children":-1},"Tackling the problem of a shared database","\u002F2012\u002Ftackling-the-problem-of-a-shared-database","2012\u002Ftackling-the-problem-of-a-shared-database",{"title":129,"path":130,"stem":131,"children":-1},"So you've got some fancy new hardware...","\u002F2012\u002Fso-youve-got-some-fancy-new-hardware","2012\u002Fso-youve-got-some-fancy-new-hardware",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":133},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":135},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7l7 7l-7 7\"\u002F>",1790886934171]