Of course, every web site/application (let’s say web app) is different, so there’s no universal setup that is good for everyone.
However, I was looking at possible server setups and these are the most common—and among these one should be able to find a solution that would work well enough for most kinds of projects.
Single server setup
This is definitely the most common setup.
Your application runs on a single machine—could be shared, dedicated virtual/physical—and includes your whole development environment (PHP, Ruby, etc.), database (MySQL or whatever), and storage.
This configuration is good for small to medium-sized websites that aren’t expected to grow that much, where high availability is not a main concern (make sure you have a reliable backup system in place).
- easy to setup: just go to any hosting company and publish your app
- cheap: you can get shared hosting for as low as $10/year, or a high-performance SSD virtual machine for $5/mo. if you need more.
- bad performance: you fight for resources with other users (in case of shared hosting), or server resources (CPU, Memory, I/O, etc.) within a single machine if you have a VM or dedicated server
- hard to scale: you can upgrade your RAM or even CPU if you have a virtual machine, but can’t scale horizontally
- no high availability: if anything happens to the machine or one of its components, your whole site goes down until the problem is fixed
- hard to diagnose bottlenecks and pinpoint performance problems
- insecure: shared hosting is somewhat less secure than being in your own walled garden, and if a website on the same server gets attacked your website might be in jeopardy, too, and will certainly suffer performance-wise
- other devs might mock you saying you’re stuck in the 90’s :-/
Separate database server
Let’s say you have a virtual or dedicated machine and private networking. You can separate the database management system—or DBMS—to improve performance and security.
- better performance: your app and DB don’t contend resources anymore
- you can scale more easily: add resources to each tier discriminately according to your needs
- diagnose performance problems more easily as you now have two smaller components instead of a huge single one
- better security (provided you have private networking) since your database wouldn’t be directly accessible from the Internet
- no mocking from other devs :-)
- more expensive
- slightly harder to setup compared to single-server setup
Now we’re talking. This is a good-enough setup for many websites and apps.
You have a load balancer (reverse proxy), which distributes incoming traffic between two separate machines which both run your app. Then, these are connected to a forth server with the database.
NOTE: if you’re wondering, a reverse proxy is the opposite of a proxy (called a forward proxy, you might have used one at school or at the office to visit Facebook or YouTube if the IT department blocked those sites). A [forward ]proxy is set up so that your computer (A) goes through B to serve you C, so that if C is blocked you can still see through B. With a reverse proxy, the exact opposite happens: the website makes you go through B while you want to visit C (hence the “reverse”). You normally shouldn’t notice this happening.
Some software you can use to implement reverse proxy load balancing is HAProxy, Nginx, and Varnish.
- load is distributed between two servers, making your app more performant
- if one server goes down, the app continues to work while you fix the problem—users won’t even notice (unless it’s the DB server, of course).
- allows for horizontal scaling, meaning you can add as many servers as you want with this setup
- protects you from attacks since the load balancer can limit too many connections at the same time
- more expensive (more servers needed)
- harder to configure
- your load balancer can become a bottleneck if improperly configured or not powerful enough
- if you don’t plan for it (ex. with session stickiness/Redis to save sessions), your users won’t use the same server every time they make a request, so your app must be stateless (ex., shouldn’t depend on RAM or temporary system resources like sessions). This means you might have to change your app a little.
- besides sessions, you have to account for SSL termination and possibly a few other aspects
Load balancing + database replication
This technique allows better performance while both reading and writing to the DB. Although it does NOT provide a complete failover mechanism, it’s still a very popular setup for medium-sized web apps.
Basically, we’re not going to have two database servers: one for reading, and one for reading and writing, which also syncs its content with the read-only machine.
- improved performance while reading from the DB, since queries are spread across two servers
- improved performance while writing, since you gain some performance by reducing the reading the machine has to do
- you must build a way to switch databases according to the type of the query you want to perform, so some coding will be needed
- as replication is asynchronous, there is a chance that the two DBs be out-of-date
- if the master node fails, you won’t be able to update until the problem is resolved
These are popular setups to host your web application. I’m looking into a lot of cool stuff which I’ll write about it, and will update this with more info.
For this article I started with the excellent article from Digital Ocean, https://www.digitalocean.com/community/tutorials/5-common-server-setups-for-your-web-application (hopefully with a simpler language but regardless writing works for me to learn).
Clip art are icons taken from the awesome free iOS 7 icon pack by Icon8—released under the Creative Commons Attribution-NoDerivs 3.0 Unported license—which I changed around and mixed together.
If there are any mistakes, please let me know in the comments! :-)