It's All ‘Last Mile’

I spent a number of years in the telecom industry, and that’s where I learned about the “last mile problem”. The last mile problem refers to the challenge of getting a communications network extended all the way out to the end customer’s premises. Building out a broadband backbone to serve a region is no small task; but actually connecting individual residences or businesses up to it is a disproportionately huge problem. The number of lines that have to be run, the widely varying types of equipment that have to be interfaced with, and the local street conditions (and authorities) all combine to make those last miles to the customers some of the most expensive and complicated legs of the network. The “last mile” concept has been used to describe a similar problem in the transport of physical goods (and even people). Moving large numbers of things between distribution centers is one sort of logistical problem; getting individual things to their final destination presents a very different – and very expensive – hurdle.

I think software development has its own form of the last mile problem. Building an application is one thing; actually getting it into the hands of customers involves a ton of other activities. The application has to be packaged in an appropriately distributable form. It has to be deployed such that it will be reachable by users – and possibly at very large scale. It has to be versioned so we can keep track of who is using what, in case users run into problems. Developers will need access to logs and metrics. Usage documentation must be written, and UI useability must be considered. These are all tasks with many known approaches, but they aren’t trivial.

Because “last mile” tasks are generally believed to be low risk and fairly well understood, they are easily overlooked in planning – which ironically can make them very expensive. For example, release cadence can be a customer-facing (and even marketing) decision; however, that release cadence can have implications for your development pipeline. I once worked at a company which served elementary school districts. Those districts would only accept major application upgrades during extended school holidays like summer break or Christmas vacation, but still required interim bug fixes in the meantime. A trunk-based, continuous-delivery workflow doesn’t work as well in such a situation, so we had to support long-lived release branches for development to continue on the main line. Not taking into consideration early-on how and when releases need to end up in the hands of users may allow a development pipeline and toolchain to form which is mismatched to the company’s actual needs. Discovering that fact late in the game can cause bottlenecks, blocked developers, and missed opportunities.

Transport companies may be able to put off solving logistics last-mile problems because they are well-researched and well-defined. Humans have, after all, been moving goods around for quite some time. We haven’t been deploying software nearly as long, however; and software last-mile logistics are not well-defined problems. The rapidly-changing nature of the field means that regardless of whatever application you’re distributing now, you’re quite likely doing it with technology that didn’t exist a few years ago. Opting to deploy your application in kubernetes-based containers is not quite as simple as the marketing would have you believe… and the sooner you start to tackle that complexity, the better. Kicking the can down the road is only a viable strategy if you know how long the road is.

The last-mile journey begins with the first step. When building applications, development teams will commonly start out by building an end-to-end “proof of concept”, then iteratively add functionality. Development and release pipelines can be incorporated into this process such that the “proof of concept” application is being built by a “proof of concept” pipeline. Test-driven development encourages the developer to start work by asking “How am I going to test this thing I’m about to write?” Release-driven development encourages the developer to also ask “How am I going to release and deploy it?” Early on, this will provoke the automation of things like ephemeral test environments. As the product matures, that capability will become invaluable in preventing bottlenecks (i.e. avoiding scenarios like “Release is immanent, so nobody deploy anything to the DEV environment for the next couple of days!”). Thinking about how an application will be tested can affect it’s design; and the same applies to thinking about how it will be deployed.

Consider your development pipeline to be a dress rehearsal for release, starting at Day One. Span that last mile with every build. Avoid kicking that can, no matter how tempting. Sure, this may slow things down early on… but it will make up for itself in productivity savings down the road. As the Build Buddha says, “Pay for it now, or pay more for it later.”