HubSpot’s core technology stack has been through a lot of change and iteration. What started as a simple content system based off a C# framework has evolved into a broad application platform. Today, our tech stack is made up of hundreds of services and dozens of full-fledged products. We’ve experimented with a lot of languages and frameworks along the way: We’ve built services in Go, Scala, node.js, and Ruby, and launched major product initiatives in Python and Java.
Looking ahead, we need a tech stack that will help us scale. We need to be able to rapidly build services and test out new products and features, quickly onboard new engineers, and allow easy collaboration across teams. That’s why Java has become our language of choice at HubSpot.
Java has come a long way; it used to slow development down with clunky frameworks, endless XML, and over-engineered libraries. But it’s evolved into a modern platform that we think is perfect for building fast, reliable services and web apps. Here’s a look at why we’ve adopted Java and some of the key benefits that I think make it right for us.
What We Like About Java: The Fundamentals
I’ll get into what we like about building Java for the web, but first, here’s a snapshot of some of its core language features and fundamentals we’re leveraging:
-
The Java Virtual Machine (JVM) is robust and outperforms many dynamic languages so we don’t have to rewrite sections of code in other languages to be performant.
-
Java has powerful library support for managing threads, collections, and network connections. That means we aren't limited when adding additional code and libraries to extend and run inside our services. We can add threads that help us monitor and debug systems. And when we want to communicate over new protocols or talk to new services, we can easily add support via a rich networking stack.
-
Modern Java IDEs have powerful and simple debugging capabilities, auto code-completion and refactoring, trivial introspection of core and third party libraries, and code generation. A rich IDE that allows developers to quickly understand code and to use new libraries without context switching into browsers is magical.
-
Java does its own garbage collection. We like the fact that Java is high-level enough to perform some of the mundane and less critical tasks for us.
-
Java is widely used. Many engineers are familiar with its syntax and libraries, and there’s a big community providing high-quality open-source frameworks.
Java Continues to Evolve for the Web
On top of its fundamentals, tooling, and community, Java has continued to evolve over time. We’ve seen lots of valuable changes in official releases and from the ever-growing (and often open-source) Java community. Some of these updates have drastically improved the way we write Java:
-
Java 8 introduced a slew of new features, like lambdas, making the language more functional than ever. We like Java but we also like light-weight and expressive code, something Java has never been known for. As Java has changed over time, it has removed unnecessary verbosity without compromising core language features.
-
Modern Java frameworks make it easy to build simple REST and JSON-based services rapidly, while open-source libraries like Guava, Guice, Hystrix, and DropWizard have made programming in Java more friendly and powerful. Companies like Google, Netflix, Facebook, Twitter, and HubSpot have made strategic investments in Java and have open sourced much of their foundational work. Building a web stack on Java is natural and lets you stand on the shoulder of giants.
-
High-quality open-source distributed systems that power much of the internet are written in Java. These include Elastic Search, HBase, Hadoop, Cassandra, ZooKeeper, and OpenTSDB.
How We’re Using Java at HubSpot
Over time, we’ve built an ecosystem around Java that’s become a competitive advantage for our engineers, and many of Java’s advantages are amplified by our scale as an organization.
-
We don’t serve templated HTML out of Java services. Instead, we produce JSON that is consumed by other Java services, internal and external clients over HTTP, and our JavaScript web applications. JavaScript is our dynamic language of choice and powers much of our front-end web stack.
-
Many of the distributed data-stores we use at HubSpot are written in Java and get top-level client support as a result. It also means:
-
Our engineers are able to quickly and easily grok the library code for these systems, providing patches and deeper insight into operational issues.
-
We are able to extend these systems, by providing our own extensions of the built-in clients. For example, we were able to easily fork and build the HBase client code to add support for Hystrix, an open-source library which improves fault tolerance of distributed system clients.
-
Because we are able to leverage a single JVM for both our application stack and systems, we can share a lot of our tooling and operational knowledge: analyzing stack traces, thread dumps, and heap dumps from these services is already part of our core operational competency.
-
We take advantage of annotations, static compilation and types to write self-documenting code so that:
-
Engineers don’t need to find or read out-dated documentation, because the code is readable and more importantly - navigable - in the IDE.
-
We can refactor critical code paths without using find/replace and regex. This makes it easier to keep code named appropriately.
-
Engineers can create and ship new services with very little code and configuration.
-
It’s easy to provide common frameworks and abstractions in Java - the building blocks our engineers, and especially new hires, take advantage of - to build reliable and modern systems. We have clean, modern libraries for tasks like making HTTP calls, delivering distributed configuration to services, and performing authentication and authorization in services. All of these libraries expose simple APIs that can be understood through the IDE, often without reading documentation, examples, or drilling into multiple abstraction layers.
-
Since we don’t have to deal with the overhead of a polyglot environment, we only need to provide a single set of high-quality components, which we have an incentive to continue to invest in and improve. And as our team and application evolves, our common Java platform allows us to maintain development speed even as engineers move between systems and teams.
By building microservices in Java and combining great libraries with sophisticated open-source distributed systems, we’re able to scale our organization and our product. We’ve been able to avoid the old pitfalls of the language by using modern Java and pushing HTML and templates into the client, keeping our backend code nimble.
Even engineers who were initially skeptical about a Java-only environment have come around. When we recently surveyed the team about our infrastructure, one said that they “really enjoyed writing code in Java” for the first time thanks to our libraries. Another said they “came in pretty skeptical of Java” but have been “converted by the maturity and niceness of the tooling in place.” Ultimately, we’re faster and better as an organization because of Java, and it’s integral to a tech stack that our engineers love building on.