As companies have shifted away from a single monolithic application and toward microservices, the places where our code lives have multiplied. Nowadays, a modern software application is split across multiple repositories, all deployed to their own servers, with some even sharing in-house libraries. But with the emergence of serverless architecture, developers have an opportunity to unlock greater productivity and collaboration. It’s time to re-embrace the monorepo.
During the monolithic era, it made sense to host all code in the same place because it was being deployed in one piece. But with the launch of Amazon Web Services in the early 2000s, companies no longer had to worry about servers, since they could use the cloud to handle processing needs. Cloud computing unlocked new architecture possibilities. Over time, many organizations shifted from a single monorepo that contained and deployed the entire application to a service-oriented architecture where the application was deployed to numerous servers. From there, developers arrived at microservices, where each service is deliberately small and only performs one function on its own server. This marked a new era: Microservices unchained teams from one another because the servers were isolated; with sequestered codebases, they could gain full autonomy. And as organizations grew in size and software in complexity, this architecture made sense, allowing teams to move fast with little coordination.
But in a microservice-based architecture, each new service typically comes with a new repo to update and maintain. A development workflow that initially required three or four different repos could balloon to include a dozen that were all interconnected. And, in an effort to prevent duplication of work and logic, internal code-sharing processes required several updates to multiple repos in order to make a change. In the past, I’ve personally had to run six different applications simultaneously in order to fix a small bug. While the added complexity of microservices made team autonomy possible, it also decreased overall developer productivity, resulting in loss of time and energy for the organization.
If cloud computing platforms are best thought of as buying someone else’s computers to run your code, then serverless computing can be thought of as renting time and space on those computers and letting the platform worry about running the code. Serverless computing frees the user from having to worry about the underlying infrastructure and dramatically lowers the barrier to entry to the world of cloud computing. As companies look to leverage this new platform and its benefits, we have the opportunity to rethink the code management practices that developed alongside the use of microservices.
If microservices allow developers to independently develop and scale their code and serverless platforms can now handle the scaling part of the equation, do we still need autonomy among teams? It’s time to reconsider the monorepo as a single source of truth for all of an organization’s software. Done thoughtfully, a return to monorepos can increase productivity, navigability, efficiency, and collaboration, ultimately providing a better development experience.
When servers are removed from the equation and managed by the platform to which the code is deployed, developers don’t need to worry about things like spikes in traffic and memory usage and can focus instead on writing clean and understandable code. Databases, for instance, can experience dramatic effects due to traffic spikes, but serverless architecture makes it possible to put additional resources in place without much extra configuration. Moreover, having a single source of truth for all of your organization’s software will only sharpen that focus. Rejoining code in one central location can thus increase developer productivity.
In a serverless architecture, all of the code is compiled down to functions that are evoked and managed by the platform. When transitioning back to a serverless monorepo, your code can therefore be organized by the end functions that are called. So instead of having to navigate each repo, developers can rely on a monorepo’s consistent structure, making it easier to understand new code. This also allows organizations to standardize and enforce coding behaviors and best practices, since all of the code is centrally located. Additionally, sharing code is much easier in a monorepo because developers no longer have to update multiple repos for a single change. Instead, the most up-to-date code is always present and being used by all of its dependents.
The adoption of monorepos can also speed up development, since developers don’t need to do discovery when thinking about linking up systems. The promise of microservices was that each service would be so small that you could glue a handful of them together to create new functionality. While this is true, it often meant that logic and work could easily be duplicated as teams continuously solved the same issues in their own silos. In a monorepo, developers can resolve issues with a common solution, avoiding the effort of duplication. When working on a new feature, developers can leverage all of the existing code in the system.
As a company’s monorepo grows in complexity, it will foster a new mindset among developers. Teams grown used to developing in their own silos will have to actively collaborate across the organization to ensure they aren’t duplicating work. Collaboration takes time, but it’s an effort that always reaps benefits. Providing opportunities for people who don’t normally interact with one another to ask questions and work together also creates visibility within organizations. Monorepos make this easier by creating a shared place for everyone to work.
For companies with legacy infrastructure for testing and maintaining multiple repos, readjusting to a single-repo reality is no small feat. Few organizations can re-architect at the drop of a hat. The good news is that monorepos aren’t an all-or-nothing proposition: Gradual adoption is possible. In the past, when my organizations moved from a single server and a monorepo to microservices with many repos, we took a piecemeal approach. We started with one piece of functionality at a time and isolated the code into its own repo and server. This same process can be useful as you combine code back into a monorepo. Begin with a few minor services and aggregate them into one serverless repo. Starting small creates room for experimentation—and allows your organization to find the right fit.