When most of us first started jobs as developers, we were pretty chuffed with ourselves when we completed a project and it WORKED. Of course, that's when our boss or other, more-senior technical personnel would look over your work and let you know that it probably is not a good idea to expect the database to be running on the same server as your application's code.
"When I was a child, I spoke as a child, I understood as a child, I thought as a child; but when I became a[n adult], I put away childish things, including silly engineering practices"
And, like most developers as their career progressed through the years, we have become more and more concerned with proper engineering and design, and rightfully so. But then other constraints imposed such as time and budget limits make it extremely difficult to bring to bear the level of engineering we would perhaps like to see implemented.
It is an age-old engineering question perhaps best summed up in the classic Project Management Triangle:
The Big Worry
While project management has its own manifestation of the issues presented by the triangle, the issues dealt with by senior software engineers in this situation typically revolve around determination of a level of engineering appropriate for the project and its constraints.
Some developers and architects seem to have a knack for making this determination; however, more often than naught, you will find that those same developers have had the benefit of years of experience including years of likely seeing many projects fail (or at least not go to spec). They, too, have very likely lost sleep over just how "elegant" a system actually needs to be.
Perhaps the biggest driver of proper engineering these days is the issue of scale, now that web applications are no longer solely the domain of the enterprise (smart phones, anyone?). Consumers place a lot of demand and expectation on the performance of the applications they use, whether they are free or otherwise.
But is it always necessary to worry, fret and panic about how your application is going to scale when it reaches its first million users?
Truthfully, only a small number of such applications actually reach those numbers on the first try. It is not uncommon for application infrastructures to be rethought and reworked after learning some lessons about the dynamics of the application in product as well as the userbase. Not that that means developers and engineers shouldn't apply some reasonable design decisions based on some reasonable assumptions or research.
Here is a list of practices that can be followed to help you get your application off the ground without necessarily worrying about how you're going to have your cloud auto-scale and auto-spin up new VM instances based on traffic demands:
Keep your application servers' instances separate from your persistence servers. No monolithic architectures!
In fact, whenever possible, keep all external services used by your application code separated from the application server. It might seem like a bit of a waste out of the gates, but you will thank yourself when your application starts to experience some real growth, both with respect to performance and with respect to isolating system failures.
Unless you know for a fact that you are going to have a lot of data and traffic coming in daily (as in several tens of thousands of users accessing several GB of data), a cluster likely is not needed. You can save time and money out of the gates, and after, if needed, you can prepare for such a transition. Note that such a transition is easier for the external services, so be careful with your own application code.
Put a reverse proxy in place ahead of your application/web servers. Trust me on this one. The low level of effort needed to properly configure NginX, HAProxy, or even Varnish pays off with both efficient routing, ease of clustering setup in the future, and what is essentially a built-in CDN/caching system.
If you have the chance (e.g. in a DevOps shop), use a service like AWS to practice setting up simple infrastructures. Much time is wasted flailing about on a first deployment trying to figure everything out, and with AWS's "free tier", this practice very inexpensive to do. And, if you have more time still, employing technologies such as Puppet, Chef, and even Docker to help automate your spin-up process will save your project a lot of time and grief.
Learn to love continuous integration and continuous delivery solutions. Jenkins is your friend (or whichever other tool you prefer, e.g. AWS CodePipeline). The time you invest in learning and embracing these tools will not only serve you well for smaller projects, but it will pay serious dividends when the time comes to scale your project or you go on to bigger projects.
As a software engineer and CTO myself, I have employed these building blocks many, many times and continue to do so today. Sure, the solutions get a bit more involved or complicated, but the building blocks remain the same.
It can be easy to get caught up in the trap of over-engineering your application and its infrastructure; however, that doesn't mean that some thought and effort shouldn't be applied at the start of the project. The points listed above may seem obvious to some, but to others it should serve as a good starting point into a much larger world.
"DevOps" is the buzzword used these days to describe those shops that have their infrastructure teams working closely with their development teams. Whether you work in such a shop, as a developer, understanding the engineering that goes into an application is crucial. Such understanding has long been eschewed in favor of allowing each "siloed" team to focus on their respective domains. It is time to get out of that mindset in order to promote stronger, more reliable solutions that can grow without breaking the bank.
By following the tips listed above, you can deliver a solution that, in most cases, is ready to perform out of the gates and can serve as a solid foundation on which to grow your application if or when the time comes--no more worrying about how much thought is enough!