Microservices have become a popular and effective design for scaling development teams in large companies. A microservices architecture enables you to build and deploy services independently, providing developers autonomy, enthusiasm, and a passion for their work. These benefits are realized because they feel a sense of control over their own destiny.
Allow me to demonstrate with a story about my time at LinkedIn. In early 2008, they asked me to do an analysis of Ruby on Rails versus Grails and tell them which one they should use. They had an app written in both frameworks and the CTO didn’t want to support both. Both platforms allowed developers to iterate quickly and turbo-charge their productivity.
My Conclusion: Allow Both.
Why? You might ask.
Because passion is the most important part of any job. When developers are passionate about the application they’re developing - and the language they’re using (notice language is secondary) - they accomplish great things.
That’s what makes a microservices architecture so beautiful. If it’s implemented right, developers can choose to work with the language or framework they’re most passionate about. And as long as they have an API that can be aggregated at a gateway layer, it shouldn’t matter.
Of course, there are hurdles to clear when adopting a microservices architecture as well. It shifts the complexity to the network and distributed systems are typically harder to maintain and monitor in production. Microservices introduce organizational and decoupling challenges so a change to one service doesn’t break another. Standards that document and enforce deployment and monitoring practices across teams are absolutely essential. Continuous integration is necessary to ensure decoupling remains intact. Continuous deployment is required to automate and simplify production pushes. It can be a lot to manage.
And what about the UI that talks to a microservice architecture? Before I jump into solutions for splitting up front ends that talk to microservices, let’s take a look at a brief history of web frameworks.
A Brief History of Web Frameworks
Web frameworks have been around for more than 20 years now! Dynamic websites started with CGI and traversed to servlets, ASP, and PHP in the late 90s. In the early 2000s, they exploded in popularity, particularly in the Java ecosystem.
|The source for the timeline above can be found on GitHub.|
That first batch of web frameworks in the early 2000s leveraged MVC and server-side rendering. Then along came Ajax, single-page applications, and the mobile revolution. Because single-page applications can be distributed in a single bundle, they became popular for mobile apps as well. You’ve probably heard of Ionic and React Native; both frameworks allow web developers to use their existing skills to develop native mobile apps.
Both server-side rendering and single-page apps have their place in the world. In fact, server-side rendering has become a recommended practice for the initial load of SPAs. Static websites generators have become popular as well, as have CDNs (content delivery networks), and front end performance optimization.
As a consultant, I was hired a few times to help solve performance problems. Clients often thought their issues where in the backend, but I found more issues in their frontends! Often, these performance issues were easy to fix by turning on gzipping, adding long-lived expires headers, combining scripts (and CSS), optimizing images, and reducing network requests.
|Combining scripts and reducing network requests is no longer an issue with HTTP/2, but frontend performance problems persist in many ways.|
This brings us to today, where it’s commonplace to mix and match your MVC framework with SPAs for more dynamic functionality. If you build the next Photoshop as a web app, you won’t want to use server-side rendering; you’ll want to build it as a SPA. On the flip side, a SPA approach makes no sense if you’re developing something like Wikipedia, where MVC or a static site generator would work well.
The Microservices Explosion 💥
The term "microservices" was first coined in 2007. Many call it Service Oriented Architecture (SOA) reincarnated, and it kinda is.
|If you’re not familiar with SOA, I suggest you read Microservices vs. SOA — What’s the Difference? from the Okta Security blog.|
Microservices blew up in popularity when James Lewis and Martin Fowler published the article “Microservices”. Adrian Cockcroft at Netflix was a big part of this movement as well. He described the architecture as "fine-grained SOA" and helped pioneer microservices at web scale. Adrian is now VP of Cloud Architecture Strategy at AWS (Amazon Web Services).
This all happened around the same year (2014) that Spring Boot was first released. Spring Cloud 1.0 was released a year later in March 2015, bringing many of Netflix’s microservices architecture principles to the Spring and Java community.
Spring Boot, Spring Cloud, and MicroProfile are some of the most popular ways to implement microservice architectures in the Java ecosystem. Micronaut and Quarkus - two relative newcomers to the space - prove there’s a lot of interest from developers and market share remaining to be won from vendors (both are actually open source projects sponsored by software companies OCI and IBM respectively).
The .NET Core framework has microservices support built-in, where it’s treated as an architecture approach. And PHP has Lumen, a popular microservices-oriented framework.
Ultimately, microservices are most successful when they’re used to scale development teams and leverage continuous deployment. They give developers autonomy and the capacity to go from idea all the way to production without depending on other teams. A two-pizza team (usually 8-10 people or 5 if they’re hungry) will often contain product people, backend folks including DBAs, UI developers, and DevOps engineers that deploy and manage production.
If your organization doesn’t allow teams to be formed this way, microservices may not be for you.
Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization’s communication structure.
If your organization has DBAs, backend developers, UI developers, and DevOps engineers separated by function, you should change your communication structures first. Organize your teams around products, then think about adopting a microservices architecture.
Once communication structures exist around products and teams own everything from idea to production monitoring, you can benefit from adopting microservices. Until then, a monolith will probably work just fine!
UI Development in a Microservices World
How does UI development work in product-centric teams, and is it possible to use different languages/frameworks on the frontend too? Keep on reading.
I’ve worked on a few microservices projects. Even though backend services were split up into separate services, the UI was often a monolith built with a single web framework that made requests to the backend API gateway. The API gateway served as an aggregation layer to expose all the various services at the same base URL.
When you generate a microservices architecture with JHipster, the resulting project is composed of a gateway and 1-n microservices. The microservice apps do not have a frontend, they just have REST APIs and persist data to their own database. The gateway serves as the aggregation layer. This is also where the UI code resides. That’s right, even though JHipster supports microservices, it only does it for the backend.
Below is a video showing where the frontend code resides in a JHipster-generated microservices architecture.
JHipster 6 generates a frontend monolith for microservices by default. It also leverages lazy-loading for Angular, React, and Vue to make the initial download and render fast (it could be even faster with server-side rendering support, but I digress).
Micro Frontends to the Rescue!️⚡️
This brings us to Micro Frontends - a hot topic with a lot of activity lately. Like the microservices article that was published on Martin Fowler’s blog in 2014, “Micro Frontends” was published in June 2019. It’s written by Cam Jackson and includes a number of integration approaches.
Cam notes that ThoughtWorks Radar has moved micro frontends from trial to adopt over the last few years:
November 2016: Assess
November 2017: Trial
April 2019: Adopt
He also describes that ThoughtWorks has witnessed some key benefits (for its clients) from micro frontends:
Smaller, more cohesive and maintainable codebases
More scalable organizations with decoupled, autonomous teams
The ability to upgrade, update or even rewrite parts of the frontend in a more incremental fashion than was previously possible
Michael Geers, another micro frontends expert, created micro-frontends.org way back in March 2017 and his first commit shows that the primary motivation for adopting micro frontends is to help scale developers:
frontend integration recipes for composing a website with multiple teams
Michael’s website provides a concise description of the idea behind micro frontends:
The idea behind Micro Frontends is to think about a website or web app as a composition of features which are owned by independent teams. Each team has a distinct area of business or mission it cares about and specializes in. A team is cross-functional and develops its features end-to-end, from the database to the user interface.
Techniques and Micro Frontend Frameworks
There are several techniques you can use to implement micro frontends. One of my favorites I learned about from listening to Micro Frontends with Gustaf Nilsson Kotte on the "Conversations about Software Engineering" podcast. Gustaf Nilsson Kotte is a developer at Jayway and he describes how IKEA leveraged micro frontends with ESI (edge-side includes), web components, and static page generation.
Michael Geers’s micro-frontends.org site explains an architecture similar to Gustaf’s, except it uses SSI and server-side rendering with Nginx.
Cam Jackson’s article has many more integration approaches, including build-time integration and run-time integration.
Notice how all three techniques involve:
Web components as the target output
Custom elements to create web components
DOM Events to communicate between frontends
Server-side rendering and SSI (server-side includes) or ESI (edge-side includes)
CDNs and cache-busting as a deployment mechanism
There’s also a couple of frameworks you can use to kickstart a micro frontends implementation:
Both definitions are taken from their respective websites. Mosaic seems like Spring Cloud for the UI, with lots of sub-projects. It’s sponsored by Zalando, which is "an e-commerce company into a multi-service platform for fashion."
What are Developers Using to Implement Micro Frontends?
I did a poll on Twitter last week and Single-spa seems to be the most popular technique/framework among my followers.
You might notice there were only 13 votes. I usually get around 200 responses when I do polls on Twitter which tells me that micro frontends are still pretty bleeding edge!
Real Developer Stories
The IKEA implementation uses a combination of static pages, SPAs, and ESI for their architecture. They have ESIs for CSS and individual components and leverage h-include for doing includes on the frontend. The cool thing about h-include is it allows them to render components of their pages just-in-time. If the component is below-the-fold, it’s not rendered. When the user scrolls to bring it into view, it invokes rendering. Lazy-loading FTW!
Spotify is another company that has implemented micro frontends. They only have ~2000 employees, but they’ve been known to be a progressive technology company. Other examples include Klarna, Zalando, Upwork, Allegro, and HelloFresh.
I asked the internet for more developer stories and received a great reply from Frederik Hahne. A fellow JHipster committer and a friend, Frederik was gracious enough to answer my questions and give some insight about why and how they’ve adapted micro frontends for their B2B integration platform wescale.
How many developers does your company have?
Frederik: Overall we are now 40 (~6 scrum team) developers working on different parts of the platform or related products/services. When we started in 2014 to work on the new platform we were one team of 4 developers.
Why did you adopt a micro frontend architecture?
Frederik: We adopted micro frontends for a few reasons: - Teams can work autonomously on different parts of the UI (the most important IMHO, as the ng1 app had a lot of problems, one team changes a bit of style/component it breaks for another) - Teams can release independently different parts of the UI (with ng1 monolith we couldn’t release when one team was not ready to release their changes) - Teams can use diverse technologies for different parts of the UI (ng1 was ok, ngX way too heavy. We wanted the teams to use what they are most confident with) - Teams can test more focused and effectively different parts of the UI
What technique(s) / frameworks(s) did you use?
Frederik: We use "Server Side Includes + Http Streaming". We have built on Zalando’s Project Mosaic and use Tailor as a layout service with a UI gateway (aka reverse proxy + auth etc).
Is it a better or worse developer experience than before? Why?
Frederik: It is much better now, but we needed a custom app to provide, as we call it a development shell (side menu, header bar with some stub functions, and faking authentication for example). Having a smaller UI bundle and better tooling helped to decrease the turn around times when developing the UI a lot. So basically, UI development is now fun again!
What were/are the biggest pain points?
Frederik: We didn’t want to have a big bang release and the ng1 app was already in production so we needed to make the ng1 app a fragment such it would work like micro frontend, so we could migrate parts to a new UI if required. We have replaced some parts, but a lot of the old UI is still in production as the value didn’t exceed the effort to replace it.
Another pain point was (and is still) the UI consistency. We have one designer who defines how components should look and work. We have a custom UI library based on Bootstrap but still, developers can do what they want (as they are no necessarily e.g. ready to use Vue components).
OK, So How Do You Win?
The title of this post promises to teach you how to win at UI development in the world of microservices. I believe UI development in a microservices world has two main options:
A monolith frontend that uses the same framework, components, and lazy-loading
A micro frontend architecture that allows any framework, leveraging web components
They both seem like pretty nice options to me. Similar to microservices, a micro frontend will likely require more initial infrastructure but allow you to upgrade a portion of your stack (e.g., moving from AngularJS to React) without doing a big-bang upgrade.
If you have teams that are passionate about a particular framework, it might be just what you’re looking for. The Grails and Rails teams I worked with at LinkedIn were very passionate about their framework choices.
Wouldn’t you like to be an enabler of developer productivity, team independence, and passion where you work? I sure would!
Learn More About Micro Frontends and Microservices
In doing research for this post, I concluded that JHipster’s monolithic UI hinders its microservice architecture. The current frontend architecture leads to coupled deployments and each team is coupled to one frontend technology - a good microservice architecture should embrace decoupling. To help improve JHipster’s microservice architecture implementation, I created a feature request to implement a micro frontends prototype (and added a $500 bounty to it).
If you’re interested in learning more about micro frontends, I found several resources in my research:
Micro Frontends by Michael Greer
Micro Frontends by Cam Jackson
If you’re interested in microservices, we have a number of quality posts on this blog: