You might have a database and a web app. But the database gets slow, so you add a caching layer. Then you need to scale up to accomodate more users. You've got to be able to back up all your users' data. And when your app gets complicated, deployments can break things, so you also need to be able to roll back quickly. Once you have a dozen or more servers going, you realize that if one goes down everything breaks, so you have to add redundancy to each part of the system, which adds even more concerns about how backups and recovery is handled. Then you need to add some search features to your growing dataset, which necessitates another kind of database to index your primary database, and more app servers. Oh, and by this point when things break, it becomes really hard to tell why things are broken, so you need monitoring and centralized logging, and whoops, those are two more kinds of databases and the associated web applications to manage them. And when you're at this scale, you have to coordinate multiple pieces of the system for any change you make, so you have additional software to manage that. And by now, you'll realize your original code was terrible, and while you are wise enough to know not to try to rewrite everything, you instead take various pieces of your infrastructure and break them into microservices in new languages, and...
Are you getting the picture?
It would be useful if there was a guide on how to scale your app wisely. > So what are the basic steps you will go through? > What are caveats and best practices per step? > What are the important choices and when do you make them?
Could you recommend a resource for answers on these questions?
I took your comment and edited it a bit:
Start: database + web app
Slow database: adding caching layer
Need to backup: starting back up all your users' data
App gets complicated, deployments break: being able to roll back quickly
You have a dozen or more servers. If one goes down everything breaks: adding redundancy to each part of the system and improve backups and recovery.
You need search features: add another kind of database to index your primary database and add more app servers.
Now when things break, it becomes really hard to tell why things are broken: add monitoring and centralized logging. Those are two more kinds of databases and web applications to manage them.
Coordinate multiple pieces of the system for any change you make: add additional software to manage that.
You'll realize your original code was terrible: you take various pieces of your infrastructure and break them into microservices in new languages.
And...
If you want to experiment with an entirely new stack of technologies intended for deploying distributed, multi-tier, scalable apps, that's cool, but don't feign surprise if it takes you more than 30 minutes.
None of it is hard, honestly - it's all well-documented things that a smart person can teach themselves how to do. And I honestly think that having one person take end-to-end responsibility for delivering one piece of functionality results in much higher quality than having twenty people specializing in a single layer as it applies to twenty different deliverables.
Of course this is a slippery slope and often devs not familiar with RPM eg end up reinventing the wheel as each deployment failure breeds distrust between teams and more workarounds and safeguards get introduced.
It should be, but well... this is something if you're using PHP.
If you're using anything hipster (ruby, iirc python, Java) you're out of luck with that.
I worked on Cloud Foundry buildpacks for a while. The PHP buildpack is actually one of the more complicated ones, because at staging time it tries to recreate a shared hosting environment in a standalone container.
The Ruby buildpack is complicated for legacy reasons, but for 99% of modern apps all it really does is run bundler and rackup.
Meanwhile every PHP app wants to keep on living in the 90s.
Arguably the Java buildpack has the simplest job, if you use a sane build tool. "Here, launch this jar".