Thankfully, Moore’s law provides us with more and more computational power over time. Thankfully, because the “overhead” of applications seems to be increasing at just about the rate of Moore! I’m speaking here of the “if you don’t have an n-tier architecture, you can’t handle volume” drumbeat that seems to eat CPU cycles faster than football players drink Gatorade®.
The big benefit of n-tier architectures, adherents say, is that you can expand any tier “horizontally” and obtain more throughput. You can use inexpensive computers to boot. Think about how much we can save. OK, this sounds like a cool thing, but there’s a real price to pay in terms of doing this which I just haven’t seen discussed much. The primary issue revolves around data access speed. The secondary issue (which is discussed in a separate article), which might be more insidious, is the inexorable march of entropy relative to systems.
Before we get to the example, let’s perform a thought experiment. When working an issue, it is sometimes useful to take the supposition to the extreme to see what you get. The supposition here is that a tiered architecture with horizontal scalability is good. The extreme would be that splitting out every module as a service would be better than not doing so—think of how easy it would be to scale! If one module was too slow, I could deploy multiple instances of it. Even better, lets break out every line of code or maybe every instruction. Obviously, this is demented, but what it should serve to illustrate is that for every problem, there is a point where breaking it apart further simply does not make any sense.
The same kind of point can perhaps less clearly be made from an architectural perspective. Just as I could design a lawn mower powered by a jet engine (“just in case I get some really tall grass”), I could design a system to handle a million records per minute. But, if I do my projections and find that at most I will need to handle 500 records per minute, building the system to handle a million is a waste of my employer’s money. The system will take longer to build, be more complex than it needs to be, and in all likelihood be more fragile than simpler alternatives. My belief is that Occam’s Razor should be considered much more frequently in the area of software development.
Let’s illustrate the issues now with some simple examples. First, consider the below table of approximate access speeds by what is being accessed (or how the access is taking place). The key for the for the initial part of the discussion is the difference in time between a local procedure call and a remote procedure call.

To illustrate the primary issue, lets consider a small program that consists of a main routine that calls 2 modules (and eventually services), called “A” and “B.” The following “specifications” also apply:
- The Main reads records from a file on frame storage (3 ms per read) and processes them sequentially.
- Each module also reads a record each time it is called but is otherwise uninteresting computationally.
- 90% of the elapsed time spent processing each record is in the I/O system and 10% is computation, primarily in Main.
The wall clock behavior of the application looks something like the below, where each cell represents 1 ms:

Based on the above, the main can process 100 records per second.
