dagblog.
← Archive

Application vs. service vs. library


One problem that comes up as you keep developing an application is that it keeps swelling as you throw new features into it, sometimes along with the new technologies you need for them. A classic example is a web application's WAR file, gobbling everything up like Otesánek, the glutton from the Czech folktale. It seems to me that hardly anyone talks about how to deal with the problem, and everyone has to learn from their own mistakes. I'll try to describe the problem with the glutton and how I think we can solve it. I'm looking at it from the perspective of our development work at GoodData, where we provide software as a service.

The glutton model

Also known as the monster.

Description: The application logic has a local interface from the JVM's point of view. All libraries must be on the classpath and must be configured and initialized properly at application startup. Calls between parts of the application are always synchronous. Code reuse happens at the library level.

Classes of problems

Deployment

Initialization time is proportional to size, particularly to the amount of configuration for application logic and the libraries in use. If we can't run the old and new versions in parallel, initialization time can increase application downtime. A deployable package in the tens of megabytes is slow to distribute if, for example, we want to deploy it across a cluster all at once.

A single class loader space dictates the use of the same library versions, especially third-party libraries. If we need a newer library version, we may have to modify and test parts of the application that the change wouldn't otherwise touch.

Runtime

Memory demands can run wild. We can't allocate memory separately to each part of the application, so the parts can interfere with each other. If one part uses more memory, the rest of the system can suffer. The same goes for virtually any resource shared at the JVM level.

Synchronous calls between parts of the application block the caller. That makes it hard to respond to a failure in a part of the system that's unnecessary for completing the request, such as audit logging or notifications.

Maintenance

When an application does too many things, taking it offline, fixing a bug or restarting it for maintenance is difficult because any of those affects the whole system. Monitoring is harder too. It's essentially a black box with a ton of responsibilities.

Solution

If parts of the application logic don't depend directly on each other, for example through a transaction context, and remote calls between them won't be a performance problem, we can encapsulate them as services. Services let us build a more loosely coupled system. That gets rid of many of the problems tight coupling causes, across deployment, runtime and maintenance. One welcome result is that we can run with a reduced set of services. If there's a problem, we can take noncritical services offline and preserve the system's main purpose. In an online gaming system the main purpose is to let players play. If a secondary system, say registration for new players, starts failing, there's no reason it should take existing players down with it.

Services can be used from other languages as well as from the ones they were written in. Their use is limited practically only by their interfaces. That gives us much better reuse. Each service can set its own terms of use in an SLA, covering things like response times or the maximum number of requests served.

Of course, running part of the application logic as a service exposed through REST or messaging introduces a different class of problems. Designing and developing a service interface can be quite expensive, for REST for example. Communicating over a network also brings reliability problems. The only thing you can rely on is that nothing is reliable. The design and implementation of each service have to account for that.

I'm hardly reviving the overused term SOA. It rubs me the wrong way, and there's so much baggage around it that it's hard to picture anything concrete. This is a lesson I learned over time.

Medium version

Related articles

Related CZ Podcast episodes