This is the first in a series of articles on our experience building a Server-Driven UI (SDUI) framework for our mobile apps, called Composable.

In this article, we’ll cover the situation we were in, the problems we needed to solve, what SDUI is and why it was relevant to us. In future articles, we’ll discuss how we built it, the pitfalls and successes and the various technologies and approaches we chose.

Our predicament

There are two consumer platforms at Auto Trader: a responsive website and mobile native apps (Android and iOS). These platforms serve 80 million consumer visits per month, with traffic split fairly evenly between them. We aim for feature and experience parity across these two platforms for consumers, but the developer experience is very different.

As the apps development team was (and is) smaller than the web development team and all features needed to be implemented and tested twice (once on iOS and once on Android), we were never able to reach feature parity with web. This situation was compounded by the nature of the native apps ecosystem: both the end product (an installed executable) and the path to production (via the Google Play Store and the Apple App Store) make shipping change in apps a lengthy process—a change that can be developed, tested and deployed to live in hours on web can take days, sometimes weeks, on apps.

Once a native app is downloaded and installed it cannot be rolled back, so our test engineers are necessarily more thorough than they need to be on web (where a bug can easily be rolled back or forward fixed). Furthermore, test automation tooling for native apps is also significantly less mature than it is on web, so we have to do much more manual regression testing on apps.

So, our predicament was clear: a small team dealing with a greater cost of change in our ecosystem meant that, despite our best efforts, we had a growing backlog of work piling up, which we were struggling to keep on top of. “Why not make the team bigger?” I hear you ask—we did! Our team has grown significantly, but we value sustainable growth and a high-performing team. As any seasoned engineer knows, simply throwing more developers at the problem often makes things worse. We needed to scale our capacity to ship change in native apps beyond the rate at which we could sustainably grow a high-performance team.


We were always late to the party.

We needed to ease this problem and improve our workflow.

  • We wanted one source of truth for app logic (both Android and iOS).
  • We wanted to cut the cost of changes and ease the store release process.
  • We wanted other development teams (both our web and back-end developers) to be able to implement features in native apps without having to teach them how to code in the Android and iOS native ecosystems.

What could we do?

We looked at several options to solve the issue.

Move content to WebViews.

We’ve long used WebViews for certain areas of the apps, but they come with several problems:

  • They’re only practical for entire pages; they don’t work well for a section of an existing screen.
  • It’s tough to make them look and work like a native app; users notice this.
  • A lot of discipline and management is required to ensure all changes suit the app client. Are the teams updating the web pages aware the app is using them?
  • Users can easily get lost navigating inside WebViews following links the app can’t handle.
  • Analytics and event tracking can become complicated, stitching web and app sessions together.
  • Our users deserve more than just a website in an app shell!

Use Flutter, React Native or another cross-platform API to rewrite the apps.

While there was the option to use an existing framework, there were a lot of drawbacks and concerns:

  • Our current codebases are very mature (over ten years old) and have a lot of logic and functionality to recreate.
  • A complete rewrite would require a costly time investment and a big-bang release.
  • Our existing app teams would need reskilling to use the new technology.
  • Even if we could target some small isolated journeys with React Native, it would still affect app size and be a potential source of inconsistencies in user experience.

Enter Server-Driven UI (SDUI)

The problem with the traditional approach, where the server sends over raw data, is that the business logic and UI live on the native clients. We needed to move that logic and UI definition to the server, where we could share it with both clients without a release.

This is the premise of SDUI. Instead of sending raw data to the clients, the server sends the UI definition, much like how websites work with HTML. The server no longer sends the data about a vehicle for the client to figure out; the server describes how the page looks! This is typically powered by a back-end service called a Back-end for Front-end (BFF).


Traditional Client Architecture.


Server-Driven UI with a Back-end for Front-end.

This approach would fix the majority of our problems:

  • We’d have a single source of truth for our logic and UI.
  • We’d only have to write once.
  • We wouldn’t have to keep doing app releases for minor changes or UI tweaks.
  • External teams could more easily contribute to the native apps.
  • It would improve our ability to experiment with UI changes remotely and measure success.

Our problem and solution were clear, but one massive question remained: how could a small team with a considerable backlog build and deliver something like this?

Read on in DIY Server-Driven UI, part 2: Composing Composable, our new framework.

For those of you following our Devoxx talk, here are the links to additional content mentioned in the talk:

Contact for talk questions:

Further reading on Kotlin DSL creation:

Enjoyed that? Read some other posts.