Backend driven UI at Flo Health

Aleksej Klebanskij
Flo Health UK
Published in
6 min readAug 4, 2021

At Flo, we develop and support native apps for two mobile platforms: iOS and Android. Over these two platforms, there are 40 million people who use and rely on Flo as their daily tool for life. As a data-driven product company, we strive to measure every change we make and the impact they have (we see everything as an experiment).

To deliver, learn, and adjust fast, we diligently strive to reduce the time-to-market. The quicker we deliver changes to our customers, the sooner we evaluate whether the changes are anticipated, the sooner and more value we bring, and the happier customers we have.

Challenges

Large-scale mobile app development comes with a set of engineering challenges. Mainly, these are related to the nature of mobile applications.

It can take weeks to release a new app version on the stores (App Store and Google Play): and even once the release is approved, we cannot guarantee that every user has the new version: some users have automatic updates turned off, and even when they update, they might skip several versions.

We work in 2-week sprints: after every sprint, there’s a 2-day code freeze, after which we release new versions of our apps on both Android and iOS stores. However, we can’t wait two weeks to publish a new article, release a new course, update daily insights, or even run a new product experiment.

Content creation and delivery

Media is a big part of our app: we need to deliver daily health insights to millions of users, and these insights have to be based on their most recent user activity. That means it’s not feasible to “pre-load” two weeks of material in advance to last until the next app version is released.

What’s more, we have a team of both external and internal experts — doctors, health advisers, content creators, bloggers, etc. — who produce new content and should be able to deliver this quality content to the right audience at the right time.

As an engineering team, we need to make sure that we enable our content creators to seamlessly deliver content to our app users.

Time to market and development cycle time

We seek engineering excellence, and we measure and improve it after each sprint. According to DORA’s Report 2019 (which considered six years of research and data from over 31,000 professionals worldwide), lead time or time-to-market is one of the top four performance metrics for capturing the effectiveness of the development and delivery process. It’s essential to mention that for six years in a row, their research has consistently shown that speed (cycle time) enables stability and stability enables speed.

Our backend (server) teams can continuously integrate their changes and release them in a matter of hours. Usually, we release several times over the course of one day.

However, due to the nature of mobile app releases (mentioned above), it’s impossible to do the same for the app.

Solutions

Backend-driven development

Unlike mobile app development, due to the stateless nature of HTTP, every request can be understood in isolation, and one can release a “new version” with every new HTTP request. With that in mind, we can ensure that once we release a new version of the service, it’s immediately delivered to our users with the next request.

The benefits of server-side development are apparent when it comes to speed of delivering changes. That’s why we try to develop with a backend-driven approach in mind at Flo. This approach enables two main things:

  1. It allows us to stay in constant contact with our users, react to changes, and deliver feedback constantly in the form of daily health insights, courses, and other educational materials and content.
  2. As engineers, we’re able to deliver in a short cycle, to increase our overall system throughput, and shorten our cycle time as a result.

UI constructor

UI Constructor (UIC) is our “in-house” framework for creating UI Elements (Views/Nodes) from JSON objects. It allows us to generate the UI for two mobile platforms on the backend so we don’t need to wait two weeks every time we need to make a change to the app: we can actually do it with the backend release.

Contracts

To establish an agreement between server and client (native mobile apps), we have a repository with UI constructor contracts. Based on these, the backend generates a JSON object describing what needs to be drawn (and how), and the clients (native mobile apps) draw a UI according to these contracts.

Layout

To align and distribute space within a container, we mostly use Flexbox, since it’s compatible with most platforms:

Elements

All UIC elements derive their contract from the Basic Element contract:

As you can see, elements are capable of handling:

  • Actions by invoking a callback function
"action_click": { // optional, can be used to pass action for an element or container
"type": "open_url",
"url": "https://..."
}
  • Analytics by reporting analytics data back to the server
"analytics_data" : { //optional, can contain any analytics information 
"screen" : "today", //example
"source" : "widget" //example
}

Content delivery

We use Contentful to allow medical experts and our content team to create different types of content. It’s an API-first content management platform for creating, managing, and publishing content on any digital channel. Contentful allows creating models (as-a-code) that describe the structure of the content. Once such a model is created, it can be filled with content and published.

After it’s published, it goes through our internal tooling and pipelines and eventually becomes accessible in our backend services (in the form of JSON objects), where it gets enriched with attributes like analytics or action_click .

How content creators are able to release the content

The last step: JSON to UI

Finally, our backend services return a JSON object with everything related to UI. This is where we can see the real flexibility and power of UIC. It allows us to:

  • Generate JSON that describes the UI (layout and its content) and parse and render on two platforms — iOS and Android.
  • Have more flexibility when it comes to running UI experiments: we can pretty much generate the UI from the backend.

However, there are some downsides as well, such as:

  • We’re mixing layout and (analytics) data together.
  • Generated UI is rather static: elements are independent of each other

What’s next

Stay tuned for the next article on UI Constructor where we’ll take a look at tooling around: how we can rapidly prototype using it and how we apply it in the different parts of the app (not just the content).

Sound exciting? Like our approach?

Come work with us and shape the future of women’s health worldwide.

--

--