Microservices: The no-bullshit guide for developers (part 1)
Over the past few years, whenever the topic of microservices arises, this familiar question also comes up: What is the best approach for developing a few/numerous/countless microservices?
In a time-honored tradition, I generally answer with a slew of additional questions: Have you already started developing? How large is the team working on the application? Have they ever developed apps in the cloud?
But the 800-pound gorilla question is this: How are you developing — on your local machine or remotely, in the cloud?
Of course, it’s not really an “either-or” question. Each option has its own advantages and drawbacks. To capitalize on some (and dodge others), microservice development often utilizes both approaches. And to add to the fun, the pros and cons of each vary with the development stage.
In this 4-part “Rookout Guide to Developing Microservices” we start (now!) by discussing some of the ways that the characteristics of microservices interact with the dev cycle and environment configuration to impact where and how to develop most easily and efficiently. In part two of the series we’ discuss developing microservices in the local environment, touching on pros and cons; the situations in which local development is preferable; and the tools that can help you debug.
The third part of the Guide will cover the pros and cons of developing in the cloud, the situations in which cloud is the best way to go, and how to provision cloud environments for development. The final post will cover some of the tools we like which can help you manage the challenges of developing in the cloud.
Here we go!
Microservices and the Dev Cycle
Development is, of course, neither a single activity nor a linear process. It is probably best envisioned as an ascending cycle or spiral, in which a developer writes code; executes it; tests how it works, determines what’s not working, why and how to fix it; and starts the next twist of the spiral by writing more code to address issues and/or move app functionality forward.
Starting in the early aughts, developers moved their entire development process onto powerful laptops. As a result, tooling for the local environment is very mature. With IDEs, sniffers and other monitoring tools providing great control and visibility throughout. With the emergence of cloud-native technologies, however, we’ve gone back to the future: End-to-end development on laptops is no longer an option.
Developing Microservices, Locally and in the Cloud
For microservices, local development is a significant challenge, for a number of reasons:
- Many apps comprise tens or even hundreds of integrated and interdependent microservices.
- Different microservices often leverage different runtimes and may be backed by various datastores.
- Testing locally is unlikely to accurately reflect concurrency, scalability, and performance.
- Finally and possibly most significantly, cloud-based services are not available on local platforms.
While these factors make some steps in the cycle very difficult — perhaps even impossible — to accomplish locally, developing in the cloud presents its own challenges.
Let’s get specific: Executing and observing code in the cloud is really, really hard. The local sniffers, debuggers and process monitoring tools devs know and love simply do not apply. Cloud tools are both less familiar to devs and provide less visibility since they are designed for production tasks and workloads, not for development and debugging.
As a result, verifying whether the code works and if not, determining what’s wrong and how it should be fixed — in short, debugging — is a significant challenge when developing in the cloud. It requires more guesswork and more time-consuming, delay-inducing iterations of the dev cycle.
So here’s the absurd choice: Execute in the test environment that most accurately reflects production, but get little info about how your code runs or where it goes wrong. Or execute locally so you have visibility into where and how things go wrong, but in an environment that’s likely to differ substantially from staging and production.
We’ll get into more specifics about when to use each development environment in future posts in this series. For now, suffice it to say that in most cases, your response when asked, “Will you develop locally or in the cloud?” should be, “Yes.”
Configuration Alignment, aka “But it works on my laptop”
“Fine,” you might say. “So do the development tasks that work best locally on laptops, and move to the cloud when you need to.” With both local and in-cloud development offering clear advantages and drawbacks, most developers end up working in both environments. When they need visibility, they take the app back to their laptop and use the familiar sniffers, debuggers, and monitors to see just what’s going on. And when they need to see how the code will behave in production, they’ll take it up to the cloud to make sure it works with the databases, storage, DNS records, TLS certificates and other cloud infrastructure that will ultimately support it.
But flipping between laptop and cloud brings its own challenges.
It goes without saying that one of the major advantages of local development is that everything you need — computing resources, storage, databases, and tools — are available right on your laptop, for much lower costs (and with less hassle) than the cloud-based services that you’ll use in production.
Of course, local setups can only approximate cloud environment elements such as managing provisioning, authentication and so on. Every additional difference increases the likelihood of issues arising later in the dev cycle once the app is deployed to the cloud.
Larger apps entail parallel development of many microservices. Aligning configurations between all developers, as well as with cloud environments, is a tough challenge. Each time any setting is tweaked, the same change must be reflected across all environments, both local and cloud. Maintaining parallel configurations is one of the most challenging, time-consuming and difficult issues associated with microservice development.
A Word About Hybrid Environments
For some cloud-based resources and infrastructure, offline replicas are simply not available. As a result, even when a dev is working locally, he’ll still need to spin up databases or other services and tools in the cloud. We refer to this as a hybrid environment.
Hybrid environments offer one big advantage, as well as (surprise!) a number of drawbacks. The big advantage of hybrid development environments is that they allow developers to access cloud resources directly from the local environment.
The drawbacks of hybrid include many of the disadvantages of both development environments — local and cloud — which we’ll cover in depth in future installments of the guide.
Summing it up
In this post, we’ve covered the challenges of setting up development environments for microservices and the importance of aligning configurations.
In our next post on developing microservices in the local environment, we discuss the situations in which local development shines. We also present our favorite tools and tricks for helping you develop locally. Don’t miss it!