Sep 25 2020
One thing I am learning as a developer working on enterprise software is the importance of a configuration management system. When you have a software system that's installed on-premises for each customer, that is configured and customized separately, managing configuration becomes a challenge. You can't just use environment variables or simple files to store config. You need to have a good strategy to deal with the configuration.  

Here are some of the best practices for managing the configuration of your software, taken from the book Pragmatic Programmer by Dave Thomas and Andy Hunt. 

When code relies on values that may change after the application has gone live, keep those values external to the app. When your application will run in different environments, and potentially for different customers, keep the environment- and customer-specific values outside the app. 

Common things you will probably want to put in configuration data include: 
  • Credentials for external services (database, third party APIs, and so on)
  • Logging levels and destinations
  • Port, IP address, machine, and cluster names the app uses
  • Environment-specific validation parameters
  • Externally set parameters, such as tax rates
  • Site-specific formatting details
  • License keys
Basically, look for anything that you know will have to change that you can express outside your main body of code, and slap it into some configuration bucket. In this way, you’re parameterizing your application; the code adapts to the places it runs. 

Parameterize Your App Using External Configuration.
If the configuration is simple, you can store it in JSON or XML files. For more complicated ones, you might need an application that stores the config in the database. When your application starts, it reads this configuration as a data structure in-memory and uses throughout the life of the application. If you change the configuration, the application needs to restart to fetch the new values. This is how we manage configuration at CityView.

Though this is a common approach to managing configuration, the pragmatic programmers recommend against it. Instead, their suggestion is to wrap the configuration information behind a thin API. This decouples your code from the details of the representation of configuration.


In this approach, the config is still external to the application, but instead of storing in a file or database, it's stored behind a service API. This has following benefits:
  • Changing configuration doesn't require the application to restart. Then next API call will fetch the latest configuration value. 
  • Multiple applications can share configuration, with correct authentication and authorization. 
The first benefit is important. Modern applications are expected to be up and running all the time. You shouldn't have to stop and start the whole app to change a single config value. Using config-as-a-service, the application always fetches the latest value from the configuration, dynamically. When config changes, there's no need to rebuild the code. 

However, I am not totally sold on this benefit. If I expose my configuration as a service behind an API, my application becomes chatty, making a lot of HTTP calls with the API, which would have been available in-memory if they were loaded as a data structure when the application started. An HTTP call is always going to be slower than an in-memory call. 

You have to use your best judgement and choose the strategy that suits the needs of the users and application and what's important to you. If the config is changing all the time and you don't want to restart app each and every time, use config-as-a-service. If the config is done initially, and changes rarely, use a static configuration which gets loaded when the application boots up.

Infrastructure as Code

Sep 24 2020
In an IaC environment, we don’t make changes to systems directly. Instead, we update the code and data that are used to create our environments.

When we administer systems this way, the code we use to control our infrastructure is not just part of our infrastructure, it is our infrastructure. It describes the network connections between machines, the machines themselves, and the applications that run on the machines.

To create a new machine, we update our machine-processable description and let the automation create it. If we do not like that change, we can revert to a previous version of that machine-processable description. We fix our infrastructure as a developer fixes a bug: We make a change to code and test it in a test environment; if that is successful, we push the change to production.

When we manage our infrastructure as code, every change would be made by updating machine-processable definition files that, when processed, created machines, deleted machines, configured systems, created files, started processes, and so on. We would gain the ability to track changes, know the history of our infrastructure, and identify who made which change. Our infrastructure would be parameterized so that we could build the same environment with different quantities, names, and locations. System administration could reap the benefits that software engineers have enjoyed for decades.


  • Reduced Cost: Manual labor is reduced or eliminated. Automation is a workforce multiplier: It permits one person to do the work of many. 
  • Improved Speed: Not only can tasks be done faster, but they can also be done in parallel. They can be done without waiting for a person to be available to do the work. 
  • Reduced Risk:  Security risk is reduced because we can prove compliance. We can reduce the risk of errors and bugs by applying software engineering techniques like unit tests and version control. 

  • Make all changes via configuration files, such as a Dockerfile or PowerShell scripts.
  • Document systems and processes in code to make it the source of truth. 
  • Use version control system to track changes in the configuration files. 
It can be intimidating to get started with IaC, especially in a preexisting environment. The best strategy is to start small. Automate one thing on one machine to get comfortable. Then manage more aspects of the system over time and build toward an environment where all changes are made via the CM system.

Pets vs. Cattle

Sep 22 2020
Currently I am reading the the Practice of System and Network Administration, by Thomas Limoncelli. In this book, I came across the concept of pets vs. cattle when it comes to managing your IT infrastructure. It's one of those ideas that changes the way you look at your servers. In a nutshell, pets are the highly customized machines and cattle are the generic machines.

Cattle-like systems give us the ability to grow and shrink our system’s scale. In cloud computing a typical architecture pattern has many web server replicas behind a load balancer. Suppose each machine can handle 500 simultaneous users. More replicas are added as more capacity is needed.

Another way of describing pets is to note that they contain a lot of irreproducible state. Cattle are stateless, or contain only reproducible state. State is, essentially, data or information. That information may be data files, configuration, or status. In a web-based application, there is the application itself plus the database that is used to store the user’s data. That database is state.

The more state a machine holds, the more irreplaceable it is—that is, the more pet-like it is. Cattle are generic because we can rebuild one easily thanks to the fact that cattle contain no state, or only state that can be copied from elsewhere.

We can turn pets into cattle by isolating the state. Imagine a typical web application running entirely on a single machine. The machine includes the Apache HTTP server, the application software, a MySQL database server, and the data that the database is storing. This is the architecture used by many small web-based applications.
The problem with this architecture is that the single machine stores both the software and the state. It is a pet. If the server goes down, our application goes down and the data is lost.

We can improve the situation by separating out the database. We can move the MariaDB database software and the data it stores to another machine. The web server is now cattle-like because it can be reproduced easily by simply installing the software and configuring it to point to the database on the other machine.
This process is also called decoupling state. The all-in-one design tightly couples the application to the data. The last design decouples the data from the software entirely. This decoupling permits us to scale the service better. For example, the web server can be replicated to add more capacity.

In such systems we no longer are concerned with the uptime of a particular machine, if it contains only the application code, which is stateless. If one machine fails, the autoscaler will build a new one. If a machine gets sick, we delete it and let the autoscaler do its job.

SQL Server Password

Sep 19 2020
Earlier today, I was having problems trying to connect to an instance of SQL Server Express running inside a container from SSMS running on my host machine. 

The container was started as follows:
> docker pull microsoft/mssql-server-windows-express
> docker run -d -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=password" -p 1436:1433 --name mydb microsoft/mssql-server-windows-express
The container is running on the IP address that I got using
docker inspect --format '{{.NetworkSettings.Networks.nat.IPAddress}}' mydb
But when I tried to connect to this instance, at the above IP address using SSMS, I got the following error:
Got the same error even if I change the case/position of the instance, e.g. `,1436\SQLExpress`, or `\SQLExpress,1436`.

Here are a few duplicates I found on StackOverflow: 

  1. Cannot connect to SQL Server express from SSMS
  2. Connect to SQL Express with SSMS
But the answers didn't help me. I did make sure that the container was up and running. I could ping to the IP address of the container. The username and password were correct.


The original password I had used was weak (no I wasn't using password used in the question, but a different one which was still weak).

After starting a new container with a password which has combinations of uppercase, lowercase, characters, and numbers, I can now log into the database using following settings.


Sep 18 2020
In operational theory, the term bottleneck refers to the point in a system where Work-In-Progress (WIP) accumulates. 

A team that produces a software application has different members performing each task: writing the code, testing it, deploying it to a beta environment, and deploying it to the production environment. 

Watch what happens when a bug is reported. 
  • If it sits in the bug tracking system, untouched and unassigned to anyone, then the bottleneck is the triage process. 
  • If it gets assigned to someone but that person doesn’t work on the issue, the bottleneck is at the developer step. 
  • If the buggy code is fixed quickly but sits unused because it hasn’t been put into testing or production, then the bottleneck is in the testing or deployment phase.
Once the bottleneck is identified, it is important to focus on fixing the bottleneck itself. There may be problems and things we can improve all throughout the system, but directing effort toward anything other than optimizations at the bottleneck will not help the total throughput of the system. 
  • Optimizations prior to the bottleneck simply make WIP accumulate faster at the bottleneck. 
  • Optimizations after the bottleneck simply improve the part of the process that is starved for work.
From: Practice of System and Network Administration, The: DevOps and other Best Practices for Enterprise IT, Volume 1