I'm working on a small team designing a process management system to be used by several different customers within the same industry. The goal of the system and high level requirements across the customers are very similar. However, as expected - once we started digging deeper into their individual needs we ended up with some pretty extensive customization required for each individual customer involving just about everything including data, input forms, validation, workflow, reporting etc.
Adding all this up we realized a multi-tenant architecture would probably be the best approach to make this happen. The backend is much further beyond design and is a RESTful api in .net being built with ServiceStack, RavenDB and Sql Server. Anyone familiar with ServiceStack will know it's extremely flexible and built with pluggability in mind - this has made implementing a multi-tenant REST api much easier than we expected. We're using a very simple convention to identify and authorize tenants by checking a value in the session belonging to each request (all "tenant-specific" requests must be authenticated so there's always a session available). So there is currently little to no need to keep track or pass a tenant id from the client in any route url. So for the backend api, we've hit our design goal of having a single code base supporting different customers with a good amount of code reuse and flexibility to customize/extend tenant specific functionality as needed.
So with the backend mostly squared away we've turned our attention to the frontend where we're really struggling to implement a similar multi-tenant approach in AngularJS. Part of the problem is the fact we're relatively new to angular. We have some experience building single-purpose apps using the standard "folder pattern" but when we look at our multi-tenant requirements here we're really struggling to tie everything together (general project structure/routes/views) to support the same multi-tenant design goals in AngularJS that we've achieved with the backend (single code base supporting reuse, flexibility & customization). The module pattern seems like a great option to "plug in" custom functionality per tenant but the big thing we're still missing is an overall architecture approach that gives us a single AngularJS code base supporting the goals mentioned above. Can any AngularJS pros help get us over the hump and recommend an approach here?
Thanks!
This is a design question so my answer is going to be high level.
A multi-tenant Client Side Web Application will have following variables most of which you have already mentioned. You should take 2 broad approaches regarding how to proceed.
Lay down what are the variations in each of the variables listed below upfront (as much as possible).
Approach a) If you think the variations in the variables across tenant is manageable
create 1 application that handles all the tenants. What is manageable
? You can do one exercise by following the Handling Variations in the variables section below. See if you can drive things by metadata
. This is understood by understanding the variations across tenants for each of the variable.
Approach b) If you think the variations are too many reconsider making these separate apps. As you go along you may find some commonality. You can re-factor that code as a common module and expose as a bower (private) artifact.
Approach a) Handling Variations in the variables
1) Look & Feel - Skin Use one CSS per tenant.
2) Data If the JSON schema differs you have a problem. I would suggest just going for Approach b). If you see some fields added+subtracted you are fine. Highly recommend creating JSON schema.
3) Input Forms I recommend driving the Forms from the JSON Schema + some metadata. Would you be able to use same AngularJS templete with a whole lot of ng-if, ng-switch for tenant variations ? If not then go for separate FORM. Are you ending up with too many such "separate FORMS" ? Then you to back to Approach b).
4) Form Validation
You can JSON schema and decorate it further with validation attributes. (Don;t know what your stack offers but in Java Bean validation annotations are pretty handy - you can externalize these at build time and bundle them with the client so that forms input fields can have validation applied pragmatically driven from the schema.)
5) Workflow If you see routing logic changing per client - use angular routers and have the routes defined per tenant.
6) Reporting Assuming that these are some views that are tailored per tenant. How much do they differ ? If you can use ng-if/ng-switch without cluttering the templates you are good to go otherwise create separate templates, views (routes can take care of the views).
7) i18n/l10n AngularJS has a bunch of utilities like $locale, ngPluralize, various filters like currency, data , number. Checkout AngularJS i18n
In summary good metadata
design, Validation decorated JSON schema
and a good routing ([AngularJS routing ][2]) design
would help you keep it a single multi-tenant Application that you can manage across a good lifetime of the product.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With