Keep it simple
This was an thought paper originally drafted in order to help government buyers understand that government technology doesn't need big flashy COTS, or to have some contractor just lift and shift the mainframe logic and processes, and that custom software that was grounded in proven technologies and architectures was actually better and more cost effective in the long run. It never got published, but it has always been a subject that I thought was worth exploring.
Government IT systems are often burdened by intricate business processes, a consequence of stringent statutory and regulatory requirements. These complexities can obscure the internal business rules, leading to a misconception among business owners that a complex technology stack is necessary to manage them. Complicated rules don't require complicated technology.
That misconception hardens into bias. Simple architectures look inadequate, so they are rejected out of hand. What gets built instead just mimics the mainframe in the cloud. Systems have the same batch jobs, nightly or routine maintenance windows, and the same flat-file handoffs, now running on managed services. The technology moved, but the design didn't.
John Gall wrote in Systemantics (1975), "A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system."
The load-bearing word is worked. Not "finished", necessarily, but working. Something real is running the whole way through, and each thing you add keeps it running. The systems that fail are the ones that spend two years in a state where nothing works yet, and find out at cutover whether the design was right.
We can build more complicated systems and business rules on top of simple solutions. Our work then becomes understanding the business rules of the government partner, and then layering those rules onto an architecture we already trust. That lets us build high-context, high-knowledge systems faster, since we are only carrying a single hard problem as opposed to two. We have halved the number of complex systems we have to understand, making our project easier to build and improve as a result.
The five things we build
Nearly everything we build falls into five categories. While the boundaries may not be black or white, those distinctions matter less than what the categories have in common.
Websites, front ends, and mobile apps
This can be anything from a Single-Page Application to a native mobile application to a more complex web site that sprawls and has a mix of content management systems and authenticated experiences.
APIs and back-end services
These are the services that fetch, translate, and transfer data between systems. Anything from a simple CRUD API to a complex facade, these are the transport layers that move data between other systems.
Reusable pipelines, platforms, and software factories
These are the systems that manage the critical infrastructure that all the other systems sit upon. While these systems can be as simple as a person managing a cloud native configuration, in our work these are typically larger scaled operations that are meant to build efficiencies into an enterprise, and accelerate development of other systems by removing the responsibilities for infrastructure and networking from application teams. The goal of these systems is to let application teams worry about the application and let the infrastructure specialists manage the infrastructure.
Data solutions, warehousing, and transformation
These projects deal with identifying, moving, transforming, and presenting data in order to make business decisions faster and better. This is a huge group of things, and includes everything from creating simple dashboards with Google Analytics to very large enterprise-wide collation of data into lakes and processing data in ways that makes it legible to decision makers.
System modernization and cloud migration
This work is taking older systems and shifting them to the cloud, or looking at older systems and replacing them with modern technology stacks in order to make them more performant and maintainable. This also includes work where we do the work to cutover from the older systems in controlled phases.
Five categories, each with known answers that you can buy, build, or hire for.
Solved problems
We are not operating on the bleeding edge in most places, nor do we need to be. Government systems are built to be extremely successful at delivering benefits and information to the American public. We are not building systems for hyperscale, nor are we solving for unbounded growth. The user population is bounded and it is known. That lets us provision for peak times with ordinary technology instead of inventing for uncertainty. Load for Open Enrollment or filing season may spike hard, but they do so on a schedule we already know. What we need is stability and correctness, because a benefits system that is down or processes a claim wrong costs someone their check.
The technical problems we face in government, as distinct from the rules they encode, are solved. We have a way to build these systems with simple technology and patterns that have been proven to work. There exists industry tested technologies, many Open Source or free to use, that we can leverage, with large pools of talent trained on these technologies ready to do the work.
Why that buys us
Cost Efficiency and Scalability
Leveraging industry-tested technologies offers a significant advantage in terms of cost-effectiveness when scaling your operations. These technologies have already undergone extensive development and optimization, allowing you to avoid the expenses associated with building and refining your own solutions from scratch. Additionally, they often come with established communities and support networks, providing valuable resources for troubleshooting and further development.
Flexibility and Vendor Independence
By adopting standard patterns and architectures, you can mitigate the risk of vendor lock-in. This approach ensures that you are not tied to a single provider and can easily switch between different vendors or technologies as needed. This not only safeguards you from potential price hikes or service disruptions but also allows you to take advantage of new and innovative solutions as they emerge.
Optimized Complexity and Resource Allocation
Starting with a simple foundation and gradually adding complexity as your system demands allows for better resource allocation and a more streamlined development process. This avoids the unnecessary costs and delays associated with overengineering or building features that may never be used. By focusing on the essential elements first and iteratively expanding your system, you can ensure that resources are used efficiently and that your solution remains aligned with your evolving needs.
Agility and Risk Management
Building complexity incrementally fosters a more agile and responsive development process. This allows you to quickly adapt to changing requirements, regulatory/statutory conditions, or user feedback. Furthermore, by minimizing upfront complexity, you can reduce the risks associated with large-scale projects and avoid costly rework or delays. This iterative approach enables you to maintain better control over costs and timelines while ensuring that your solution remains relevant and effective.
None of this is an argument for building less than the government needs. The rules will stay complicated, because the statutes and regulations behind them are complicated, and no architecture is going to change that. What we can decide is whether to carry that complication once or twice. If we start from a simple architecture that already works and layer the rules on top of it, the hard part of the system is the part that was always going to be hard, and everything underneath it is something we already know how to build.