Moving Away from the Monolith — “Shift left?”
Just about everyone in tech is going to mention “shift left” at some point, but what are they actually talking about? It’s the heart of DevSecOps. Think of it as moving control processes as early in your development lifecycle as possible. It gives us a powerful set of tools to begin the migration away from the “long, monolithic development lifecycle” to a modern, fast moving, optimized pipeline.
So what’s it mean to “move control processes left?”
“Control processes” are steps that make sure we we build a good product. That includes things like testing the software, but also extends into more subtle areas: Compliance management, risk reduction, operational reliability. Here’s a good example: As a bank, how do we make sure all of our regulatory requirements are met every single time we issue a loan?
If we think about how this looks in a traditional, somewhat waterfall development lifecycle, it reveals a pretty long tail. Here’s a simplified diagram based on a customer in the finance industry:
A developer may not receive feedback (in the form of a bug, defect report, feature enhancement) for more than three weeks after they write code. Even in the best case, the developer finishes what they were working on, moves on to something new, and then gets feedback from peer review days after they commit their work.
This is inefficient. It leads to constant context switching and rework. It delays the delivery pipeline, making it impossible to ship software in a rapid cadence. It also fosters large, monolithic “bundling” of features into big, complicated deployments — which, in and of themselves, become difficult to manage and further slow down the delivery pipeline.
“Shift left” is simply moving as many of these activities as early in the pipeline as possible. Small changes can have dramatic outcomes. Just compressing the peer review cycle into the development cycle makes a significant difference:
Everything we move earlier in the development cycle makes development more efficient and contributes to accelerating the pipeline.
By tightening the feedback loop, we can eliminate context switching, saving more time. And by focusing on smaller features, the control processes become less complicated and further accelerate the pipeline.
By making continuous iterative improvement the entire pipeline can be collapsed:
So how do we make these improvements without sacrificing our control processes?
Small iterative changes over time will yield increasingly productive results. Don’t try to change everything at once (which itself would be a monolithic project). Instead, make small changes — embody your kaizen every day by making constant small improvements.
- Make security everyone’s job. Rather than expecting security controls to be engineered in after the product has been built, give the development team responsibility for delivering a fully secure finished build. Embed a security expert into the team to provide the support they need, and start teaching everyone how to embed security from day one. Rather than running penetration tests downstream, enable ephemeral environments so penetration testing is done on every (or nearly every) commit.
- We can also embed compliance into the core product by making it a part of the development specification — in other words, build it into every feature’s acceptance criteria. Make compliance the engineer’s job, not an obligation to come back and check off later. Features must include automated verification of compliance requirements (written as tests, by the development team). As with security, embedding compliance means we’ll need sufficient time and attention from an embedded compliance team member early in the design cycle.
- Make automated testing the only path to higher environments. This means the only way a build moves from development “up” to staging, review, or release is if it passes all it’s acceptance criteria — in a 100% automated fashion. Rather than trying to inject quality by testing the build downstream, embed a quality expert into the team. Engineer quality in by having the development team build their own automated tests — the quality expert shouldn’t write tests, they should instead look over the acceptance criteria and test implementation to make sure it’s fit for purpose.
- Test everything in isolation. That means isolating components by creating natural boundaries between them (services should only use one another’s API). This makes it possible to validate each component in a stand-alone manner, using mocks to represent other services. By taking other components out of the picture we can accurately test a service: Controlled inputs equal known, controlled outputs. This improves testing, improves independent deployability, and lets teams move at their own maximum velocity.
- Stop shipping big feature sets. One reason we do ship big, monolithic builds with many features is because everything is tightly tied together. Use feature flags rather than trying to coordinate complicated, interdependent system changes. Feature flags let us code in a change and turn it on or off — testing it on a small audience, and quickly “flipping the switch” to go back to previous behavior if anything goes wrong. It simplifies deployment, enables canary testing (trying out a feature on a small group), and eliminates most roll backs since you just flip the feature to “disabled” if something goes wrong.
At the heart of it is automation, and making things small. Move away from the monolith on all levels. Think about small features, small increments, and small changes that — over time — will get you where you want to be.
Originally published at https://blog.bosslogic.com.
Cover photo by Dids.