At New Relic, we’re always looking to add new functionality to our products. To do that well, we go through a standardized process of evaluating new tools and technologies to find the right fit.
In this blog post, we explore the choice we made to deploy an existing application framework to support our new Alerts features—instead of building our own. We hope this offers some insights into how we choose what tools to use, and is helpful to folks facing similar technology decisions.
About New Relic’s environment
Like many modern software shops, New Relic follows a microservices architecture, with small, composable services packaged in reusable containers and deployed independently from one another. The services are built around business capabilities, and they come together to represent a single application. They use lightweight communication mechanisms, like HTTP, and provide clearly scoped APIs. Because there are so many of them, they must be deployed in an automated way to reduce risk to the overall application. And although the microservices architecture gives teams the independence to use different languages, many of our teams have standardized on JVM-based languages for their services.
A key aspect of our environment is our reliance on containerization. Each service is wrapped in a container, isolating the runtime environment inside so that it can be deployed to any host with minimal prerequisites. This is important because every team assumes responsibility for the review, merge, build, and deployment of the code they write. Containerization allows those engineers to control everything from the operating system to how the application is packaged and executed with minimal knowledge of where the container is deployed. At the same time, our Site Engineering teams don’t need to know a lot about what’s inside the containers.
With microservices and containers in mind, we were looking for several critical framework characteristics:
- Ease of building the application
- Self-contained bundling of the application code
- Straightforward application execution
- Supportability of the application
Finally, there is the people consideration—we look for tools and approaches that match the skills and experience of our engineering teams.
Using an open source framework
When building New Relic Alerts, one of our first decisions was whether to use an existing web application framework or to create our own framework based on components that support the ethos of microservices.
Due to the rising popularity of microservices, there are more choices than ever when it comes to existing microservices frameworks for the JVM. These include:
Our choice: Spring Boot
Our team chose one of these existing frameworks, Spring Boot, for two main reasons: our engineers had previous experience with the Spring Framework, and we thought it best fit our requirements. Specifically, Spring Boot gave us five key characteristics:
- Extensibility: Spring Boot uses convention over configuration, but customization is straightforward. (For example, we use Jetty over the default Tomcat container.)
- Reduced friction: The framework handles boilerplate configuration and setup, such as logging, configuration, security, etc. That helps the team focus on business logic instead of plumbing.
- Pragmatism: The core offering focuses on currently adopted technologies for integrations and doesn’t try to predict needs that might arrive years in the future. It leaves bleeding-edge extensions up to the community.
- Familiarity with the underlying technology: Spring Boot is built on top of the Spring Framework and Java, both of which are strong suits of our team.
- Support: There’s an active open-source developer community for Spring Boot, and it’s backed by Pivotal, which has a vested interest in improving and expanding the framework.
Spring Boot also meets our criteria for containerization listed above:
- Easy builds: For application building, it provides first-class Gradle build support out of the box.
- Self-contained distributions: It produces an executable JAR file with all dependencies included, so there’s just one executable JAR to deploy.
- Simple application execution: The executable JAR does not require additional commands or permissions to run.
- Supportability: For support, it provides a collection of “actuator” HTTP endpoints that expose environment/configuration information, health status, runtime stats, and other data.
While there are almost certainly other items that are more important to other teams, the team I am part of felt that this set of criteria resulted in a choice we are happy with—and that supports the reality of our runtime environment.
The choice is not without trade-offs, of course. But what we lose in control or flexibility by being tied to the Spring Framework and not some other DI/IoC implementation, we gain in stability and pragmatism with regards to the curation of the framework.