Growing Slowly

Every website begins its life with a single developer and a single line of code. Figure 1-1 shows a simple configuration of a Rails application connected to a database. You will likely spend quite a bit of time developing your application on this setup before it’s ready for its first user.

A basic website configuration

Figure 1-1. A basic website configuration

When it’s time to launch, there some issues that ought to be considered. Figure 1-2 shows the same configuration, but with redundancy at the application level, and failover at the database level.

There are two copies of the application so that in the event one machine fails, there is still another that can handle incoming traffic. Similarly, in the event of a hardware failure on the database machine, a copy that is a transaction or two behind can be brought online quickly.

A basic website configuration with failover and redundancy

Figure 1-2. A basic website configuration with failover and redundancy

Even if you are barely using any of the resources on either the application or database machine, redundancy and failover are a very good idea. At this point, neither of these considerations is aimed at managing load—that comes later. Rather, both are intended to ensure the availability of your web application. Reprovisioning a machine, configuring it, and loading all your software and data from backups can cause quite a bit of downtime. During that time, your customers can find your competitors’ sites, and they are likely to form negative opinions about your site’s reliability as well.

With this configuration, and perhaps even a good deployment strategy, there is plenty of work within the application and data layers that can be done before you need to add any additional complexity to your system in the form of encapsulated services or asynchronous processes. Depending on the feature set of your web application, this may even be as far as you need to go. You are already satisfying a number of the criteria that define the elusive concept of “enterprise.”

There is, within an enterprise, the need to scale horizontally as well. Only so many engineers can work in one codebase before no one can work at all. Even if there is only one chef in the kitchen, there is still only so much space for the sous-chefs.

A common way to deal with this human scaling problem is to break up a large application into smaller pieces, or services, each responsible for a specific function within the enterprise. It’s no surprise that the software splits often follow organization boundaries so that individual teams can take on full ownership of their pieces of the overall system.

Each service has its own full stack that mirrors the stack of the traditional website from Figure 1-2. The difference is that a service is responsible for a small fraction of the duties that make up the entire website, usually one specific, specialized group of related functionality. It’s possible—and sometimes preferable—to abstract all database access behind services. The front-end website then becomes a consumer of these services and has no need for a database of its own, as shown in Figure 1-3.

A front-end website backed by services, which in turn are backed by relational databases

Figure 1-3. A front-end website backed by services, which in turn are backed by relational databases

When you add services into the mix, it’s hard to argue your system is not enterprise.

There are a number of other components commonly found in an enterprise setup. Figure 1-4 shows a generic enterprise configuration. Powering the front-end website are a number of services. There are also a collection of asynchronous processes that receive information from services via a messaging queue. In addition to the front-end website, there is a web services layer aimed at providing external clients with a subset of the functionality available inside the firewall. There is also redundancy and failover in all critical places. Finally, each service database feeds a data warehouse, which powers site reporting and decision support.

Note, of course, that simply replicating this configuration is not enough. Each piece of the system is an independent, isolated, and encapsulated system in its own right and deserves thorough and thoughtful design. What goes where and how to implement each individual unit is as much an art as it is a science.

A generic enterprise architecture with redundancy and failover

Figure 1-4. A generic enterprise architecture with redundancy and failover

Get Enterprise Rails now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.