I’ve assembled a detailed post on my experience scaling my Meteor app to support 1000+ daily active users, which I’m currently doing on 1-3 Galaxy compact containers managed by my galaxy-autoscale package.
You can read the article for all the nitty gritty details, but I’ll list some key bullets here for easy digestion.
Scaling tips
None of these should come as any surprise, but since I was able to see the real-life critical importance of these common tips:
-
Add the right MongoDB indexes. This is easy, just use recommendations from slow queries tool.
-
Enable oplog trailing. Also easy, some setup with your MongoDB provider and a line of config.
-
Think carefully about every publication you write. If you write any pub that does
return myCollection.find({ });
, you should probably rethink your approach, as this will likely just break once you start adding users.
End result of my scaling efforts
After finishing the work on scaling my app, here are the final numbers on how well I was able to get my app to scale.
For every 100 concurrent users using my app, I needed to provision 0.5 ECU and 512 MB of memory.
I was able to easily do this by horizontally scaling Galaxy compact containers using my autoscale package.
Keep in mind for my app and expected audience, this was a perfectly acceptable level of scaling and I basically stopped further optimization once I got here.
Also the numbers above were conservative enough to leave a margin on both resources, at that level I sit at around 40% total CPU and 80% memory in use steady state.
When I was starting the project I did not really understand how to write good pubs and Meteor methods, so ended up back-fixing many of the poor ones until I got good performance. If I was starting a new project, I’m confident I would be able to make a far more efficient app than the first time.
How Meteor performed
There were basically no surprises when it came to watching the app go from development to production. Any extreme latency could always be traced down to pubs which were trying to deliver MB of data to each client, or loops on the client which were calling 30+ method calls at once.
The only surprise was how much better oplog trailing performed than the diff-and-poll method, as I was able to support the same number of users on a third of the resources. Every performance article recommended to use it, but I didn’t expect the impact to be so dramatic.
The end story is that for small/medium apps, I can confidently state with real-world proof that Meteor is ready to scale. If you are making an app that requires extensive interactivity and real-time communication with a server, than Meteor is a great choice for both the easy development experience and the efficiently of the production environment.
Sure you can support far more users using a system that provides a more static page with cached data, but that is where you have to decide before you write the first line of code what are you willing pay per connected user in order to provide the best possible user experience.
If you want to provide a real-time collaborative app to allow hundreds of people to interact real-time, than you can do so with Meteor on a budget of well under $100/month, easy. Add that to the fantastic development experience and continued awesome releases (thanks for 1.5 code splitting!) by the MDG team, I’m still thumbs up on continued Meteor development.