Working with Docker APIs

Docker’s popularity is due to its simplicity. Most developers can cover quite a bit of ground just with build, push & run commands. But there could be times when you need to start looking beyond CLI commands. For instance, I was working with a customer who was trying to hook up their monitoring tool to Docker Engine to enhance productivity of their ops team. This hook is typically to pull status and stats of docker components and report / alert on them. The way monitoring tool would achieve this is by tapping into APIs provided by Docker Engine. Yes, Docker Engine does provide REST HTTP APIs which can be invoked by any language / runtime with HTTP support (that’s how Docker client works with Docker Engine). Docker even has SDKs for Go and Python. For this post I will be focus on how you can access these APIs using HTTP for both Linux and Windows hosts. Finally we will look at how to access APIs for Docker Enterprise deployments.

Accessing APIs with Linux Hosts

For Linux, Docker daemon listens by default on a socket – /var/run/docker.sock. So using our good old friend CURL here’s the command that you can execute locally to get the list of all containers (equivalent of docker ps)

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -X GET http:/containers/json

But how about accessing the API remotely? Well simple you need to expose a docker endpoint beyond socket using the -H flag for docker service. Link shows you how to configure the same. With that configuration in place you can fire CURL again but this time access the IP rather than the socket.

curl -k  -H "Content-Type: application/json" -X GET

So can just anyone access these APIs remotely? Is there an option to restrict or secure access to APIs? The answer is yes. Docker supports certificate based authentication wherein only authorized clients (possessing cert obtained from authorized CA) can communicate to Docker engine. This article covers required steps in detail to configure certs. Once configuration is done you can use below curl command to access Docker APIs.

curl -k --cert cert.pem --cacert ca.pem --key key.pem

Accessing APIs with Windows Hosts

Unlike Linux which uses sockets, Windows uses pipes. Once you install Docker and run the pipelist command you should see ‘docker_engine’ in the pipelist. You can access this pipe using custom C# code or use Docker.DotNet NuGet Package. Below is a sample code with Docker.DotNet library to retrieve list of containers using ‘docker_engine’ pipe.

DockerClient client = new DockerClientConfiguration(new Uri("npipe://./pipe/docker_engine")).CreateClient();

var containerList = client.Containers.ListContainersAsync(new ContainersListParameters());

foreach (var container in containerList.Result)

In addition, similar to Linux you can use the -H option to allow for TCP connections and also configure certs to secure connection. You can do this via config file, environment variables or just command line as shown below. You can refer to this article for securing Docker Engine with TLS on Windows. Once configured you can use Docker.DotNet to invoke Docker APIs.

dockerd -H npipe:// -H --tlsverify --tlscacert=C:\ProgramData\docker\daemoncerts\ca.pem --tlscert=C:\ProgramData\docker\daemoncerts\cert.pem --tlskey=C:\ProgramData\docker\daemoncerts\key.pem --register-service

Accessing APIs with Docker Enterprise Edition

So far we have invoked APIs for a standalone community docker engine but Docker has other enterprise offerings including Docker Enterprise Edition (EE). If you are not familiar with it check out my post to create a single node test environment. Universal Control Plane (UCP) part of Docker EE provides a set of APIs which you can interact with. Also unlike standalone engines, Docker UCP is secure by default. So to connect to UCP you would need to pass username password credentials or use certs from the client bundle both of which are shown below. With credentials you retrieve an AUTHTOKEN and pass that token for subsequent requests to gain access.

#Accessing UCP APIs via Creds
AUTHTOKEN=$(curl --insecure -s -X POST -d "{ \"username\":\"admin\",\"password\":\"Password123\" }" "" | awk -F ':' '{print    $2}' | tr -d '"{}')

curl -k -H  "content-type: application/json" -H "Authorization: Bearer $AUTHTOKEN" -X GET 

#Accessing UCP APIs via Client Bundle
curl -k --cert cert.pem --cacert ca.pem --key key.pem 

Hope this helps in extend your automation and monitoring tools to Docker!


Deploying Docker Enterprise on a single node

Most developers find installing Docker fairly straight forward. You download the EXE or DMG for your environment and go through an intuitive installation process. But what you have there is typically a Docker Desktop Community Edition (CE). Desktop editions are great for individual developers but Docker has lot more to offer to enterprises who want to run containers at scale. Docker Enterprise provides many capabilities to schedule and manage your container workloads and also offers a private docker image repository. The challenge though is while it’s fairly easy to install Docker Desktop it isn’t quite the same to install Docker Enterprise. Docker Enterprise invariably requires installing Docker Enterprise Engine, installing Universal Control Plane (UCP) with multiple manager and worker nodes, Docker Trusted Registry (DTR) – a private image repo (similar to public Docker Hub), and other components.

In this post, I am going to simplify the setup for you by creating a single node sandbox environment for Docker Enterprise. Hope you will find it useful for your POCs and test use cases. For setup all you will need is a single node VM. You can use any of the public cloud platforms to spin up that single node. For this post, I have setup a Red Hat Enterprise Linux (RHEL) m4.xlarge (4 vCPU & 16GB Mem) instance on AWS. Please note the key components of Docker EE including UCP & DTR only run on Linux platforms. You can install additional Windows nodes later as workers to run Windows workloads.

STEP 1: Install Docker Enterprise Engine
To begin you would have to sign up for free 1 month trial for Docker EE. Once you create docker hub account and fill out the contact details required for trial you should get the below screen.

Screen Shot 2019-07-08 at 3.57.35 PM

Copy the storebits URL and navigate to it in your browser. Here you will find packages for different OS versions. Now RDP into your EC2 instance. Add the relevant docker repo to your yum config manager. I will use RHEL since that’s the OS of my EC2 instance.

$ sudo -E yum-config-manager --add-repo "storebitsurl/rhel/docker-ee.repo"

Then install the docker EE engine, CLI & containerd packages.

$ sudo yum -y install docker-ee docker-ee-cli

STEP 2: Install UCP (Universal Control Plane)
UCP is the heart of Docker Enterprise. It allows for running containers at scale, across multiple nodes, let’s you choose an orchestrator, provides RBAC enabled web UI for operations, and much more. The UCP installer runs through ‘ucp’ container image installing ucp agent which in turn bootstraps services and containers required by UCP. I have added comments to command options something you might have to remove to execute it successfully.

docker container run --rm -it 
 docker/ucp:3.1.7 install #ucp image is stored on docker hub
 -v /var/run/docker.sock:/var/run/docker.sock #mount docker sock
 --host-address #private IP of the node
 --san #public IP of the node
 --admin-password YourPassword #set the default password
 --force-minimums #for cases where node configuration is less than ideal

Upon completion you should be able to browse your public IP ( and access UCP UI shown below. To login use the ‘admin’ username and password ‘YourPassword’.

Screen Shot 2019-07-26 at 6.24.19 AM

STEP 3: Install DTR (Docker Trusted Registry)

DTR installation takes a similar route to UCP. It uses a container image ‘dtr’ with install command.

docker run -it --rm docker/dtr install
--ucp-username admin
--ucp-insecure-tls #ignore cert errors for self signed UCP certs
--replica-http-port 8080 #choose a port other than 80 to avoid conflict with UCP
--replica-https-port 8843 #choose a port other than 443 to avoid conflict with UCP
--dtr-external-url #this will add the external Hostname / IP to DTR self-signed cert 

Once the command completes successfully you should be able to browse DTR UI on https port (

Screen Shot 2019-07-26 at 6.33.59 AM

STEP 4: Deploy an App

Let’s deploy an app to Docker EE. For this I would pull an ASP.NET sample image, create a org and repo in DTR, tag image for DTR repo and upload it. Post upload we can use docker stack to deploy the application. To begin let’s create an organization and repository in our DTR.

Screen Shot 2019-07-26 at 5.06.37 AM

Now let’s pull the image from Docker Hub, Tag it and Push it to DTR.

docker pull
docker tag
docker image push

Next create a docker-compose.yml file with below instructions.

version: "3"
# replace username/repo:tag with your name and image details
replicas: 1
condition: on-failure
cpus: "0.1"
memory: 50M
- "3776:80"

Once file is created run the docker stack deploy command to deploy listed services.

docker stack deploy -c docker-compose.yml aspnetapp

You should be able to browse app with node’s public IP on port 3776; in my case

Screen Shot 2019-07-26 at 6.38.43 AM.png

In future, we will dig into more Docker EE features but hope this single node setup provided you a jumpstart in exploring Docker Enterprise.

Happy Learning 🙂 !

What is DevOps?

Though the notion of DevOps has been around for years I still see folks struggling to articulate what DevOps really is. Like recently in our user group meeting the participants highjacked the session for 30 minutes debating what DevOps stands for without really arriving at a conclusion. Similarly, I have seen architects, sales teams and developers, struggle to explain in simple terms to their management as to what is DevOps. In this post, I will share my thought process and would like to hear from you if you have a simpler way of communicating the DevOps intent.

Traditionally software development has been a complex process involving multiple teams. You have developers, testers, project managers, operations, architects, UX designers, business analysts and others, collaborating to create value for their business. The collaboration among these teams requires handshakes which often cause friction (leading to non-value adds). For instance, the handshake where UX designer develops UI and then developers add code, or the handshake where analyst captures requirements and project team builds desired features, or the traditional handshake between developers and testers for code validation, and so on. One such critical handshake is between developers and operations where developers typically toss software over to operations to deploy it in upstream environments (outside of developer’s workstation). Unfortunately, members of these two teams have been ignoring concerns of each other for decades. Developers assume code will just run (after all it ran on their machine) but it rarely does. And that’s where DevOps comes in to rescue.

Considering above, it would be safe to summarize that DevOps is any tool, technology or process that can reduce friction during the handshake of Developers and Operations (thereby creating more value for their business e.g. faster time to market). Now this could be app containerization bundling all dependencies into single image, or it could be setting up Continuous Integration and Continuous Delivery pipelines to allow for robust consistent deployments, or adopting microservices architecture for rapid loosely coupled deployments or it could be infrastructure as a code to allow for reliable version-controlled infrastructure setup, or AI enabled app monitoring tools to proactively mitigate app issues or even reorganizing teams and driving cultural changes within IT organization. But once the DevOps objectives are clear it’s easy to devise your strategy and approach.

Does this resonate with you? Look forward to your comments.

TOGAF – Quick Reference Guide

TOGAF is The Open Group Architecture Framework – a framework for Enterprise Architecture. In this post I am going to provide a summary of this framework to create a quick easy reference for fellow architects. Open group reports TOGAF is employed by 80% of Global 50 companies and 60% of Fortune 500 companies, if that motivates you to adopt / learn this framework.

So what’s enterprise architecture? Who can be an enterprise architect (EA)? Should every IT architect aspire to be one? Architecture word in enterprise architecture still conveys ‘organization of a system’ just that you are now alleviating from system level organization (typically tiers / layers) to an enterprise level organization of business capabilities & supporting IT ecosystem. If you are a system architect (SA) you can certainly alleviate to an enterprise architect, though you need to weigh it carefully. EAs are different beasts. They certainly have more visibility, are close to business,  up in the corporate ladder (due to alignment with overall enterprise), but at the same time they aren’t too close to technology. So if you rejoice technology, enjoy being close to code, trying out cool stuff, being hands-on with technology innovations, etc., EA may not be the right thing for you. EA’s role is lot more involved with business, people and processes. Now I am not saying EAs don’t mess around with technology, or SAs don’t deal with processes, but ratios are mostly skewed.

Now let’s understand what TOGAF has to offer. TOGAF essentially provides guidance for going about enterprise architecture. To start it recommends a methodology for doing enterprise architecture called ADM (Architecture Development Method). It then goes on describe typical deliverables produced throughout the ADM (Content Framework), how to logically organize them (Enterprise Continuum) and store them (Architecture Repository). For enterprise starting fresh there is guidance on creating architecture capability and how to adopt / adapt ADM for a given organization. TOGAF aims at being comprehensive, and often gets cited as being bloated (or impractical as critics call it). This is true to large extent. I haven’t come across an organization that follows TOGAF verbatim, at the same time it’s hard to find an organization EA practice that hasn’t been influenced by TOGAF. Hence it helps to look at TOGAF as a reference guide than a prescription.

Let me answer one last frequently asked question – Is TOGAF dated / dead? After all, version 9.1 was released in December 2011. Isn’t that quite long in today’s rapidly changing word? Is TOGAF still relevant? Or what’s the use of TOGAF in a digital world? As mentioned earlier, TOGAF is not bound to technology advancements such as Cloud, AI or Digital. TOGAF framework holds and will work with any underlying technology. For instance, when SOA (Service Oriented Architecture) emerged there was no modification done to TOGAF ADM, rather TOGAF provided additional perspectives as to how SOA would map to ADM phases (may be Open Group could have a separate SOA guidance, rather than integrating that guidance in TOGAF publication). The same applies to other technology initiatives. As an EA you should have a handle on market innovations, and how your business could leverage them, but how you go about aligning those two – it stays the same.

With this background let me provide you with a quick overview of TOGAF components. At heart of TOGAF is the ADM method consisting of Phases A-H, along with a preliminary phase and centralized requirements management.


  • Preliminary Phase is used to identify business drivers and requirements for architecture work and capturing outcome in Request for Architecture work document. Depending on organization EA maturity this phase will also be used for defining architecture principles, establishing enterprise architecture team / tools, tailoring architecture process, and determining integration with other management frameworks (ITIL, COBIT, etc.).
  • Vision phase (phase-A) focus it to elaborate on how new proposed capability will meet business needs and address stakeholder concerns. There are various techniques like Business Scenarios which TOGAF recommends for assisting in this process. Along with capability one needs to identify business readiness (organizational), risks involved (program level) and mitigation activities. Outcome of this phase is a statement of architecture work and high level view of baseline and target architectures (including business, information systems & technology).
  • Next three Phases B, C, D are to develop these high level baseline and target architectures for each – business, information systems (apps + data) and technology (infrastructure), identify gaps between them and define the roadmap components (building blocks) which will bridge that gap. These architectures and gaps  are then captured in architecture definition document, along with measurable criteria (must do to comply) captured in architecture requirements specification. At the end of each phase a stakeholder review is conducted to validate outcomes against the statement of architecture work.
  • Phase E is Opportunities and Solutions. Goal here is to consolidate gaps across B, C, D phases, identify possible solutions, determine dependencies across them and ensure interoperability. Accordingly create work packages, group these packages into portfolios and projects, and identify transition architectures wherever incremental approach is needed. The outcome of this phase is a draft architecture roadmap and migration plan.
  • Next Phase F is migration planning. While Phase E is largely driven by EAs, phase F will require them to collaborate with portfolio and project managers. Here the draft migration plan is further worked upon assigning business value (priority) to each work package, cost estimates, risk validations, and finalizing migration plan. At the end of this phase both architecture definition and architecture requirements document are completed.
  • In phase G (implementation governance) the project implementation kicks in and EAs need to ensure that implementations are in accordance with target architecture. This done by drawing out architecture contracts and getting those signed from developing and sponsoring organizations. EAs will conduct reviews throughout this phase and will close it out once the solutions are fully deployed.
  • What’s guaranteed after phase G is ‘change’. Organizational drivers do change either top-down or bottom-up leading to changes in enterprise architecture. Managing this change is what phase H is all about. Here EAs perform analysis of each change request, and determine if the change warrants an architecture cycle of its own. This often requires an architecture board (cross-organization architecture body) approval. Typical outcome of this phase would be a new request for architecture work.
  • Central to these phases is requirements management. Requirements management is a dynamic process where requirements are interchanged across phases and also at times between ADM cycles.

In addition to ADM, TOGAF offers guidelines and techniques which will help you adopt / adapt ADM. For instance, there might be cases where you might skip phases or change order of phases. Consider an enterprise committed to adopt packaged solution, where you might do business architecture after information systems and technology architecture. Other is where you develop target architecture before baseline architecture to ensure there is more effective transition (not getting boxed into the existing capability). In both these cases you are adapting ADM to your specific enterprise needs.

Next let’s discuss architecture deliverables for each of the phase. We spoke about architecture definition and architecture requirement documents. Wouldn’t it be nice if there was a meta-model which would dictate the structure of these documents ensuring there is consistency across ADM cycles? This is where architecture content framework (ACF) comes in. Metamodel for individual artifacts can be thought of as viewpoint from which view (a perspective for related set of stakeholder concerns) is created. TOGAF categories all viewpoints into catalogs, matrices or diagrams. Furthermore these viewpoints are used to describe architecture building blocks (ABB), which are then used to build systems (ABBs are mapped to solution building blocks (SBBs) in phase E).


So now we have enterprise architecture development methodology and a way to define its deliverables to ensure consistency. What else? How about classifying and storing these artifacts? If you look at a large enterprise there could be hundreds of ADM cycles operating at any given point in time. Each of these cycles would generate tons of deliverables. Storing all the deliverables in a single bucket would lead to chaos and minimal reuse. This is where enterprise continuum (EC) along with architecture and solution continuum comes in. Continuum is used to establish an evolving classification model starting from Foundation to Systems to Industry to Organization for all the architecture artifacts. These artifacts, along with content metamodel, governance log, standards, etc. is stored in architecture repository. There are two reference architecture models included in TOGAF documentation – first one is TRM a foundation level architecture model and second one is III-RM which is a systems level architecture model.

Finally framework gets into the details of establishing architecture capability within an organization. It talks about the need of Architecture Board, its role and responsibilities, including architecture governance (controls & Objectives) and compliance (audit). For the latter two TOGAF includes a governance framework and compliance review process. Guidance also touches upon maturity models (based on CMM techniques) and necessary role skill mapping.

That was TOGAF summary for you. I strongly encourage to read open group publication. Many find it a dry and lengthy read. But it’s the best way to learn TOGAF and a must read if you want to clear the certification. Though it’s highly unlikely that getting certified in TOGAF will overnight establish you as an enterprise architect, but it’s a first good step in that direction.

All the best for your exam, if you are planning for one. Hope you found this post useful!

NuGet Package Restore, Content Folder and Version Control

I was recently explaining this nuance to a Dev on my team, and he suggested I should capture this in a blog post. So here we go. First some NuGet background.

NuGet is the de facto standard of managing dependencies in the .NET world. Imagine you have some reusable code – rather than sharing that functionality with your team via a DLL, you can create a NuGet Package for your team. What’s the benefit you may ask?

1) Firstly NuGet can do lot more than adding a DLL into your project references. Your NuGet package can add configuration entries as part of the installation, execute scripts or create new folders / files within Visual Studio project structure, which would greatly simplify the adoption of your reusable code.

2) Secondly as a package owner you can include dependencies to other packages or DLLs. So when a team member installs your package, she will get all the required dependencies at one go.

3) Finally the NuGet Package is local to your project, the assemblies are not installed on your system GAC. This not only helps for a clean development, but also at build time. Packages don’t have to be checked into the version control, rather at build time you can restore them on your build server – no more shared lib folders.

It’s quite a simple process to create NuGet Packages. Download the NuGet command line utility, organize artifacts (DLLs, scripts, source code templates, etc.) you want to include into their respective folders, create package metadata (nuget spec), and pack them (nuget pack) to get your nupkg file. You can now install / restore the package through Visual Studio or through command line (nuget install / restore).

Typically NuGet recommends 4 folders to organize your artifacts – ‘Lib’ contains your binaries, ‘Content’ contains the folder structure, files, which will be added to your project root, ‘tools’ contains scripts e.g. init. ps1, install.ps1, and ‘build’ contains custom build targets / props.

Now let’s get to the crux of this post – the restore aspect and what you should check into your version control. When you add NuGet Package to your project, NuGet does two things – it’s creates a packages.config and a packages folder. Config files keep a list of all the added packages, and packages folder contains the actual package (it’s basically an unzip of your nupkg file). Recommended approach is to check-in your packages.config file but not the packages folder. As part of NuGet restore, NuGet brings back all the packages in the packages folder (see workflow image below).


The subtle catch is NuGet restore doesn’t restore content files, or perform transformations that are part of it. These changes are applied the first time you install NuGet package, and they should be checked in the version control. This also goes to say don’t put any DLLs inside the content folder (they should anyways go to lib folder). If you must, you will have to check-in even those DLLs inside your version control.


In summary, NuGet restore just restores the package files, it doesn’t perform any tokenization, transformation or execution as part of it. These activities are performed at the package installation, and corresponding changes must be checked into the version control.

WS-Fed vs. SAML vs. OAuth vs. OpenID Connect

Identity protocols are more pervasive than ever. Almost every enterprise you would come across will have a identity product incubated, tied with a specific identity protocol. While the initial idea behind these protocols was to help enterprise employees use a single set of credentials across applications, but new use cases have shown up since then. In this post, I am going to provide a quick overview of major protocols and the use cases they are trying to solve. Hope you will find it useful.

WS-Fed & SAML are the old boys in the market. Appearing in early 2000s they are widespread today. Almost every major SSO COTS product supports one of these protocol. WS-Fed (WS-Federation) is a protocol from WS-* family primarily supported by IBM & Microsoft, while SAML (Security Assertion Markup Language) adopted by Computer Associates, Ping Identity and others for their SSO products. The premise with both WS-Fed and SAML is similar – decouple the applications (relying party / service provider) from identity provider. This decoupling allows multiple applications to use a single identity provider with a predefined protocol, and not care about the implementation details of identity provider per se.

For web applications, this works via a set of browser redirects and message exchanges. User tries to access web application, the application redirects user to identity provider. User authenticates himself, identity provider issues a claims token and redirects user back to the application. Application then validates the token (trust needs to established out of band between application and IdP), authorizes user access by asserting claims, and allows user to access protected resources. The token is then stored in the session cookie of user browser, ensuring the process doesn’t have be repeated for every access request.

At a high level there isn’t much separating the flow of these two protocols, but they are different specifications with each having its own lingo. WS-Fed is perceived to be less complex and light weight (certainly an exception for WS-* family), but SAML being more complex is also perceived to be more secure. At the end you have to look at your ecosystem including existing investments, partners, in house expertise, etc. and determine which one will provide higher value. The diagram below taken from wiki, depicts the SAML flow.


OAuth (Open Standard for Authorization) has different intent (the current version is OAuth 2.0). It’s driving force isn’t SSO but access delegation (type of authorization). In simplest terms, it means giving your access to someone you trust, so that they can perform the job on your behalf. E.g. updating status across Facebook, Twitter, Instagram, etc. with a single click. Option you have is either to go to these sites manually, or delegate your access to an app which can implicitly connect to these platforms to update status on your behalf. Flow is pretty simple, you ask application to update your status on Facebook, app redirects you to Facebook, you authenticate yourself to Facebook, Facebook throws up a consent page stating you are about give this app rights to update status on your behalf, you agree, the app gets an opaque access token from Facebook, app caches that access token, send the status update with access token to facebook, facebook validates the access token (easy in this case as the token was issued by Facebook itself), and updates your status.

OAuth refers to the parties involved as Client, Resource Owner (end-user), Resource Server, and Authorization Server. Mapping these to our Facebook example, Client is the application trying to do work on your behalf. Resource owner is you (you owe the Facebook account), Resource Server is the Facebook (holding your account), and Authorization Server is also Facebook (in our case Facebook issues the access token using which client can update status on Facebook account). It perfectly ok for Resource Server and Authorization Server to be managed by separate entities, it just means more work to establish common ground for protocols and token formats. Below screenshot depicts the OAuth2 protocol flow


Web community liked the lightweight approach of OAuth. And hence, the question came – can OAuth do authentication as well, providing an alternative to heavy lifting protoo WS-Fed and SAML? Enter OpenID Connect is about adding Authentication to OAuth. It aims at making Authorization Server do more – i.e. not only issuing access token, but also an ID token. ID token is a JWT (JSON Web Token) containing information about authentication event, like when it did it occur, etc. and also about subject / user (specification talks of a UserInfo Endpoint to obtain user details). Going back to the Facebook example, here the client not only relies on Facebook to provide us an opaque access token for status updates, but also an ID token which client can consume and validate that the user actually authenticated with Facebook. It can also fetch additional user details it needs via Facebook’s UserInfo Endpoint. Below diagram from OpenID connect spec indicates the protocol flow.


OP in above case is OpenID Provider. All OpenID Providers have the discovery details published via JSON document found by concatenating provider URL with /.well-known/openid-configuration. This document has all the provider details including Authorization, Token and UserInfo Endpoints. Let’s see a quick example with a Microsoft offering called Azure Active Directory (Azure AD). Azure AD being a OpenID Provider, will have the openid configuration for it’s tenant available at

Fairly digestible, isn’t it 🙂 ?

Evolution of software architecture

Software architecture has been an evolutionary discipline, starting with monolithic mainframes to recent microservices. It’s easy to understand these software architectures from an evolution standpoint, rather than trying to grasp them independently. This post is about that evolution. Let’s start with mainframes.

The mainframe era was of expensive hardware, having powerful server capable of processing large amount instructions and client connecting to it via dumb terminals. This evolved as hardware became cheaper and dumb terminals paved way to smart terminals. These smart terminals had reasonable processing power leading to a client server models. There are many variations of client server models around how much processing a client should do versus the server. For instance, client could all the processing having server just act as centralized data repository. The primary challenge with that approach was maintenance and pushing client side updates to all the users. This led to using browser clients where the UI is essentially rendered from server in response to a HTTP request from browser.

Mainframe Client Server

As server started having multiple responsibilities in this new world like serving UI, processing transactions, storing data and others, architects broke the complexity by grouping these responsibilities into logical layers – UI Layer, Business Layer, Data Layer, etc. Specific products emerged to support this layers like Web Servers, Database servers, etc. Depending on the complexity these layers were physically separated into tier. The word tier indicates a physical separation where Web Server, Database server and business processing components run on their own machines.

3 Tier Architecture

With layers and tiers around, the next big thing was how do we structure them what are the ideal dependencies to have across these layers, so that we can manage change better? Many architecture styles showed up as recommended practice most notably Hexagonal (ports and adapters) architecture and Onion architecture. These styles were aimed to support development approaches like Domain Driven Design (DDD), Test Driven Development (TDD), and Behavior Driven Development (BDD). Themes behind these styles and approaches were to isolate the business logic, the core of your system from everything else. Not having your business dependent on UI, database, Web Services, etc. allows for more participation of business teams, simplifies change management, minimizes dependencies, and make the software easily testable.


Next challenge was scale. As compute became cheaper, technology became a way of life causing disruption and challenging the status quo of established players across industries. The problems are different, we are no longer talking of apps that are internal to an organization or mainframes where users are ok with longer wait times. We are talking of global user base with sub second response time. Simpler approach to scale was better hardware (scale up) or more hardware (scale out).  Better hardware is simple but expensive and more hardware is affordable but complex. More hardware meant your app would run on multiple machines. That’s great for stateless compute but not so for storage where the data now would be distributed across machines. This distribution leads us to famous CAP (Consistency, Availability and Partition tolerance) theorem. While there are many articles on CAP, essentially it boils down to – network partitions are unavoidable and we have to accept them. This is going to require is to choose between availability and consistency. You can choose to be available and return stale data to be eventually consistent or you can choose to be strongly consistent and give up on availability (i.e. returning error for the missing data – e.g. you are trying to read from a different node than where you wrote your data). Traditional Database servers are consistent and available (CA) with no tolerance for partition (active DB server catering to all requests). Then there are NoSQL databases with master slave relationship, configurable to support strong consistency or eventual consistency.

CAP Theorem

Apart from scale challenges, today’s technology systems have to often deal with contention. E.g. selecting an airline seat, or a high discount product that everyone wants to buy on a Black Friday. As multitude of users are trying to get access to the same piece of data, it leads to contention. Scaling can’t solve this contention, it can only make it more worse (imagine having multiple records of the same product inventory within your system). This led to specific architecture styles like CQRS (Command Query Responsibility Segregation) & Event Sourcing. CQRS in its simple terms is about separating writes (command) from reads (query). With writes and reads having separate stores and model both can be optimally designed. Write stores in such scenarios typically use Event Sourcing to capture entity state for each transaction. Those transactions are then played back to the read store to make write and read eventually consistent. This model of being eventually consistent would have some implications and needs to be worked with business to keep the customer experience intact. E.g. Banana Republic recently allowed me to order an item. They took my money and later during fulfillment they realized they were out of stock (that is when things became eventually consistent). Now they refunded my money, sent me a sorry email and allowed me 10% discount on my next purchase to value me as a customer. As you would see CQRS and Event Sourcing come with their own set of tradeoffs. They should be used wisely for specific scenarios rather than an overarching style.


Armed with above knowledge, you are now probably thinking can we use these different architecture styles within a single system system? For instance, have parts of your system use 2-tier other use CQRS and other use Hexagonal architecture. While this might sound counterproductive, it actually isn’t. I remember building a system for healthcare providers, where every use case was so different – appointments, patient registration, health monitoring, etc. Using a single architecture style across the system was definitely not helping us. Enter Microservices. The microservices architecture style recommends to break your system into a set of services. Each service can then be architected independently, scaled independently, and deployed independently. In a way, you are now dealing with vertical slices of your layers. Having these slices evolve independently, will allow you to adopt a style that’s more befitting to the slice in context. You might ask, while this makes sense for the architecture, but won’t you just have more infrastructure to provision, more units to deploy and more stuff to manage? You are right, and what really makes Microservices feasible is the agility ecosystem comprising of cloud, DevOps, and continuous delivery. They bring automation and sophistication to your development processes.


So does this evolution make sense? Are there any gaps in here which I could fill? As always, will look forward for your comments.

Image Credits: Hexagonal Architecture, Microservices Architecture, 3-Tier architecture, client server architecture, CQRS architecture, Onion architecture, CAP Theorem