Hi, Aaron here! In our last article, we spoke about ideal design principles for the upcoming architectural shift in the world of cloud computing.
Cloud development has become prohibitively complex, and the current generation of solutions have low-level interfaces that require extensive investment from developers and operators to understand how to configure, learn, assemble, and scale them properly. For a new architectural shift to occur, we need approaches that absorbs the cognitive load, not streamline it.
Guiding Principles
First, let’s quickly recap the main design principles I spoke about in my previous post. A solution should:
- maintain benefits from existing architectures
- keep tools and programming languages usable
- integrate with an ecosystem instead of trying to replace it
- ensure user code is recognizable, debuggable, and patchable–even in production
In this post, I’m going to describe how we took these principles into account while developing Klotho, which is a technology that lets you write cloud applications the way you write local ones, then compile them into cloud-native ones.
Maintain benefits from existing architectures
There has been a continuous discussion among backend and service developers about whether things should be built using one strategy (monoliths) or the other (microservices). There are no one-size-fits-all solutions, because there’s always a trade-off involved.
Monolithic development offers high productivity, ease of deployment, and a straightforward observability story. Microservices offer flexibility in fault isolation, resource tuning and team autonomy. Unfortunately, microservice-based architectures usually involve piecing things back together – back into the monolith’s basic architecture, but with duct tape. As a result, the benefits of neither solution are fully realized.
When building Klotho, we zoomed out and asked, “What aspects of computer engineering can we apply to bridge that gap?”. We concluded that a key characteristic in the new architecture must be the convenience of monolithic development, coupled with an adaptive system that leveraged the benefits found in microservices architectures. Most importantly, it has to reduce the cognitive load for developers, while maintaining configurability and control for operators.
By focusing on developer and operator intent, we created a solution based on ease of use through separation of concerns. Using three different programming constructs, Capabilities, Requirements, and Directives, developers and operators can specify what parts of the application should be cloud-aware, what additional tradeoffs Klotho should consider for your application, and what specific overrides are required.
Solution: Developers should write code the way they know best. We leverage their intent early on to determine what backend wiring and analysis is done behind the scenes to properly meet their needs. Requirements and Directives allow developers and operators to provide more fine tuning and controls without developers needing to change the code.
Keep tools and programming languages usable
When there was a general transition from monoliths to microservices–and then from microservices to serverless–we saw people frustrated repeatedly asking the same questions. How do I deploy? How do I make this on Azure? How do I spin up a new version?
Developers face a challenge keeping up with the latest cloud practices, infrastructure, and tools. It is especially true when a developer’s primary concern is not the infrastructure but the application they are developing.
Rather than reinventing solutions to already solved problems, we should be able to re-apply the solutions that worked well in the previous architecture, while still reaping the benefits of the new architecture.
Solution: New architectures should be supersets of their predecessors.
Integrates with an ecosystem instead of trying to replace it
Most ecosystems require buying a whole suite of products. Apple users, for instance, frequently use other Apple products such as iTunes, iPads, etc, to get the most out of their product. When another company offers a better solution for one piece of the ecosystem, the cost of changing over typically outweighs the benefits.
For our industry to continue progressing and improving, we need to focus more on making compatibility more accessible. Given the amount of existing open source projects, why recreate what already exists?
We’re not trying to create a new spec or create our own cloud with Klotho. People already use industry standards and tools for that. Rather, we looked at the possibility of converting existing applications to work with a new infrastructure. Klotho could then be integrated into your existing toolset and CI/CD pipeline. You could use the same source code, IDE, programming language, linting, libraries, and SaaS products that you are already using.
We just make things easier. Given a local application, a few Klotho annotations is all you need to produce a slightly modified cloud version of your application along with infrastructure-as-code code, such as Terraform. Artifacts produced can be read and used without Klotho. They can also be deployed directly to your cloud account.
Solution: We integrate with existing industry-standard products so you have the best of all worlds.
Ensure user code is recognizable, debuggable, and patchable
Existing infrastructure solutions do some really clever things. They tell people how to code and how to operate their services. If you follow their rules, you will receive the benefits they advertise.
But someone has to deploy and operate the service. Some say, well, it’s open source – you can look at it, download it, and make changes. However, most companies lack the time and expertise to do so. Eventually, you end up in a situation where an entire company’s technology and business depends on somebody knowing how to manage a system that’s half managed by someone else.
When something breaks, you don’t know whether it’s on your side or if it’s in the magic box under someone else’s management. Like hiring a clockmaker, you can see what’s inside, but you will never know the inner workings. Although you can take it apart, you won’t know how to put it back together without a professional.
In the real world, this means that whenever there is an outage, you have to call a third party. Hence, if they disappear or want to charge you more, you’re stuck relying on someone else. Moving away from this type of solution is virtually impossible.
We believe that a solution should be simple enough that you can operate it yourself. You should be able to fix or patch anything that breaks, regardless of whether it’s your fault or ours, and without us getting involved.
To accomplish this, we take all the complexity of what something runs outside of how it runs. Additionally, we only bundle pieces relevant to a particular solution at a given time. We will only provide you with what is necessary for your service to run, not a bunch of extra pieces that are difficult to understand.
To the extent possible, we leverage the open source community, so when we put things together, we use existing open source libraries and frameworks. We reuse a lot of what exists in the simplest and most standard ways. We want you to choose the software you want to develop in and make it cloud deployable and tuneable with minimal changes to your application.
Solution: We empower you to understand your own systems without relying on a third party, by using clear best practices and bundling relevant pieces. We write it for the cloud the way you would have.
Architecture with Klotho
Our goal with Klotho is not to shift the responsibility of our architecture elsewhere. We want to absorb complexity, not pass it on to another developer, operator, or third party. You do not have to do all the work we did before to accomplish the same result.
Simply start with your own application and write your own code. In your code, you provide us with your intent through high-level annotations. You run Klotho, and that’s it, your application is now cloud native.
We built Klotho by bringing together three groups of people and technologies that have not traditionally worked together-compiler theory, applied distributed systems, and constraint-based planning. Through our past experiences we saw the connections between these disciplines, and recognized that we could create something fundamentally new.