A SaaS platform has many different shapes, sizes and use-cases. Like websites. Can you be a bit more specific about what your needs are? There are basically 2 main types that I would use with Meteor
1 replicaset database, 1 meteor application on 1 server. Good for companies with just a few customers that use the system occasionally. (cheapest, and easiest setup). This works in most low load cases. Keep in mind that preventing privacy accidents where customers can see other customerās data is more present here. Also if using Meteorās account system, 1 username must be unique across all customers
A sharded database and 1 meteor application on multiple servers. Generally the way to go. Provides good separation and prevents load sharing between customers, but is more expensive in resource usage and is more complex to set up
@cloudspider, thank you for your suggestions and advice on this. I just wonder, is it ever appropriate to use more than one database? I mean, a database per customer?
Right now, I have it to where I have (1) Application and (1) Database per customer, and itās working out fine. Iām now working to break out a portion of the project into one central application for specific tasks that are longer running ā yet still keep the multiple databases. I had thought about using one database, but have concerns about creating a bottle neck.
Ah I see. Yes it can become a big issue to have 1 database per customer and just 1 application for all customers. Its because of how Meteor (and other platforms that use sockets and in memory collections / caches) deal with collections. This can however easily be overcome by putting namespaces. My recommendation is always to use a slug form client abbreviation. For example: If Google would be your customer, its going to be google. You might want to abbreviate long names to prevent database limitations regarding character limit: Facebook becomes fb.
1 Database per customer is perfectly fine. The time spent is then usually on the DevOps side. For example if you want a customer to register itself it has to automatically generate that database and connection etc etc.
For as far as the bottleneck counts. Keep in mind that it should be possible to horizontally scale your Meteor app. If 1 customer requires a lot of resources, it might cause other customers to experience delays.
I think that you might want to stick to the 1 database and meteor app per customer approach. Just spent your time on continuous integration workflows! Automate the build and deployment steps of your app so that each application will be updated automatically after a commit / push to your repository. This will remove all complexity from the app side, because they become dedicated to 1 customer. That is unless you want to have some sort of global admin login functionality. However, thatās still possible.
@cloudspider Iām using similar approach (1 DB, multiple apps) but Iām wondering if there will be issues while scaling the number of app instances as the connections and OPLOG tailing to the DB grows.
I have no insights on how your application is used. Few users might load the database intensively based on how they use it how well queries can be reused by other users etc etc. Scaling the database should be fine. MongoDB is really good, if not build for that purpose. The oplog tailing is Meteor specific and might become an issue when you start to have a lot of changing data. To overcome that you can then still decide not to use the oplog for some collections and only for parts that really require realtime functionality like chat apps and auction apps.
Could you explain this more, Iām not sure I understand you. I have one application with one database per customer. Are you saying this is bad/wrong somehow?
Iād like to add a worker service that runs on its own and does file processing and other long running tasks, therefore it needs access to all the customerās dbs:
You could also just use PeerDB that lets you describe relations which are then enforced from oplog, so that you could have schema record representing all of the keys or records per customer.
In terms of programming, my best practices for developing a SaaS MVP right now would be:
Meteor and the basic packages - aldeed:simple-schema, iron:router, aldeed:tabular, accounts-base/ui/password, sacha:spin, react-template-helper, less/sass
Semantic UI or Bootstrap
Blaze as data container templates that use react-template-helper to load React components with Meteor data via helpers
React - Container/component architecture - containers manage state, call Meteor methods, and pass props to (usually) functional components. Example: class MessageListContainer extends Component vs const Message = function (props) {}
Services architecture - Domain objects are broken into at least one service object each. Service objects contain methods for business logic broken into small, often re-useable functions. Meteor methods, cron, migrations, and publications all call service object methods. Example names: MessageService, MessageMigrationService, UserService
The reason is that methods can also run on the client-side, for optimistic UI updates. I would recommend having 2 separate method folders: one for server-only methods and one for isomorphic methods. But Iām using local packages anyways, so my app folders are usually quite empty.
Well, one one hand, it forces you to clearly modularize your app, so everything that belongs to a certain domain (including assets and such) becomes a separate package. Of course, this could also be achieved by using ES6 modules and a folder structure designed for this domain separation.
The biggest advantage, however, is that you can re-use such packages across several apps, by putting them into a special folder referenced by METEOR_PACKAGE_DIRS. You need some functionality like content rating? Just include the package youāve already developed for another app, without copying the code around or using private NPM packages, This is the main reason why I absolutely love the Meteor package concept.
One third reason is that only packages let you define clearly which code becomes part of a mobile app and which become code part of a web app. Without packages, you would have to use isCordova() and conditional includes a lot. Packages automate this task. This is something Node packages are dearly missing.
I donāt really think anyone can give you a best practices answer with boilerplate.
Either, SaaS involves tons of back-end scalability, because a true SaaS application has the provider handling literally everything behind the scenes. This means that you need to be prepared to host ALL your customersā data, be responsible for redundancy, global availability, performance of everything. Itās not a cheap or easy endeavour, would likely take months or years of work, so I donāt feel that any amount boilerplate could prepare you for that. Itās also just not within the scope of any framework, whether itās Meteor or Apollo or anything to handle that for you. You need hardware and serious back-end/database skills from a deployment and administrative standpoint. Itās not really about just being a good web dev.
Well, youāre talking about two different things.
Using just one database instance would, indeed, create a bottleneck which is why the common practice with MongoDB is to create replica-sets and sharded instances across multiple servers, of the same database however.
However, the way it sounds like youāve got it set up now is youāre having your customer manage their own database instances that they provide credentials for your app to connect to? Thatās more of a hybrid SaaS instead of a pure SaaS app where you handle everything. Itās a good compromise for customers that want to administer their own data as opposed to leaving it to you. Having a separate database per customer that you manage yourself doesnāt seem that appropriate to me, tbh. You just need to have a data-model (i.e. stay away from big sub-documents and multiple nested objects, and use reference collections instead) that is properly indexable and efficiently searchable so that customers donāt need to wait forever for their data.
But the original point still stands, you should shard your db and distribute replica sets across multiple servers, as well as instances of your app itself, around the world so that your customers have a good experience with the service no matter where they are.