In most cases, the IT and software challenges of enterprises and ISVs diverge greatly. However, as every business is becoming a software business, there are instances where all companies, regardless of size or industry, have similar concerns. Existing applications are one of those concerns. These apps generally have expansive user bases, entrenched customers, and existing support models. They often also lack a clear technological path to modernization. How do software vendors update these existing money-making applications without interrupting the lines of business that depend on them?
In a series of blog posts, I will look at one particular type of existing application architecture – the client-server app – and describe a prescriptive approach to phasing this architecture into a cloud-based SaaS model over time while preserving customers, support, and revenue. This is an approach we’ve successfully used with our Apprenda partners. I’m going to focus on how the app architecture can be deconstructed and moved to the cloud in phases.
First let’s look at the typical client-server application in its current state:
For the purpose of this article I’ll use .NET as reference, but the same general approach goes for client/server app written in Java. The vast majority of existing client-server apps we see are built upon the one-server-to-many-clients model, as opposed to a peer-to-peer architecture. The typical business is a single ISV, or enterprise LOB, that delivers the server software on top of resold (VAR) hardware and the installation and support of desktop clients on user workstations. The customer runs all components on-premise and leverages their own workstations and network for communications.
I imagine this sounds very familiar to most readers. When you visit the doctor’s office, do the nurses carry around laptops and as they ask you questions they click through hundreds of forms checking things and collecting your answers? That’s client-server, and it usually all takes places on the local network. Somewhere there’s a closet in that office with a server. As someone who used to travel constantly to replace noisy server fans at customer sites, I know this to be true. In the time of desktop computing, when “a workstation on every desk” was the mantra of the tech industry, it made perfect sense to put the software where the compute power was – on the workstation. It wasn’t a bad model for the time.
The challenge is how to transition from this model to a modern SaaS-based model built on cloud compute resources. How do you preserve your own IP and keep customers happy while also removing the need for each customer to operate their own server instance? Perhaps more fundamentally more important: why would you want your apps to undergo this transformation?
Simply put, much more than hardware has changed over the years:
So, we’ve established the current state and provided reasoning why it is no longer adequate. Now let’s look at a phased approach to correcting this situation.
The first step of migrating to the cloud is to relocate the “server” component of the application functionality. Properly architected client-server apps already have a demarcation point between the client and the server (communication over a network), so any refactoring should be neatly isolated. We’re essentially saying the “network” for communication is now the Internet.
The goal in this phase is to run a hosted web service that “looks” like the server component so that the clients can be redirected. However, complexity comes from one integral change to the architecture – under the SaaS model, one server “instance” ought to be able to serve multiple clients (end users from distinct customers):
This is multi-tenancy – the idea that a single application instance can simultaneously handle the operations of multiple customers while keeping both their execution space and data isolated from one another. Salesforce.com was the poster child for multi-tenancy in the early 2000s. Every customer went to the same Salesforce.com and the logic to separate user1@companyA from user1@companyB was built into Salesforce’s application architecture.
Generally, server business logic is broken into distinct web services that handle functional aspects of the app that may need to scale differently, but the details of how depend entirely on the application itself. In our de facto multi-tenant sample application, we show this by separating CRUD operations from admin operations, presuming that there will be more users than admins.
On Apprenda, web services are independent deployable units within the same logical application definition, so this maps nicely. Furthermore, our guest application API actually contains all the tenant isolation logic necessary to make a single-instance multi-tenant web service – and the web service doesn’t even need to actively participate. That’s right, Apprenda makes applications multi-tenant even if they do not contain the code to do so.
For example, without Apprenda:
var greeting = "Hello " + firstname;
This statement effectively means nothing unless the application code itself stores, tracks, and populates the variable firstname. It means even less in a multi-tenant scenario because you certainly can’t store the variable in shared memory that is being accessed by tenants who should have zero knowledge of each other.
On Apprenda, the same statement can be backed by Apprenda’s multi-tenant API (this can be done through configuration in some cases, but here I’m purposely showing the code difference):
var greeting = "Hello " + UserContext.Instance.CurrentUser().FirstName;
In this case, not only does Apprenda provide the value for the user’s first name, but it is provided in real-time context for the user executing the current request to the app. That alone is hugely impactful to the amount of time it takes to transition from on-premise server to SaaS web service(s).
Apprenda’s API has multiple implementations — one of which is the Remote API. We use the Remote API in situations where off-platform clients need to authenticate and communicate with on-platform services. It handles the communication, authentication, and, most importantly, the context persistence (UserContext on the client == UserContext on the server) for every request.
Thus, deploying web services on the Apprenda platform and using RemoteAPI (which can, depending on the app, simply be configured in), allows clients to communicate with newly migrated business logic hosted in the cloud.
There are, of course, many permutations of application architectures. Phase 1 described in this post is intended to be a reference. A future post (Part 2) will continue with the app migration and describe how the next step is to develop a modern client application, then seamlessly connect it to the same web services created in Phase 1.
As always, there are many details not described here. If you are curious about what we can do for your applications, contact Apprenda today or connect with me on Twitter at @mattammerman.