Migrating our API to be more UI Centric

Photo by Jason Goodman on Unsplash

A few years ago, Thumbtack decided to revamp how it built its APIs from business centric models sent via REST JSON to UI centric models sent via GraphQL. Efe Karasabun, a former engineer at Thumbtack, previously talked about some benefits of switching technology to GraphQL. This article will discuss some of the benefits we’ve seen switching from using business centric models to UI centric ones. Before going further, I should clarify what I mean when I say that a model is “business centric” vs “UI centric”.

A business centric model closely mirrors how the backend stores an object in, for example, its relational database. When a client receives a business model in the API, it’s up to them to determine how to display specific fields to the user. Because this logic is on the client, the client needs to understand what each field represents. For example, is it a price tag or a customer’s name? If it’s a customer’s name, is it their full name, first name, or first name + last initial? These are all things the client needs to know so that they can use these fields.

Example of a business centric mode
An example of what a business centric model could look like. Note that it requires joining data across many objects. It also requires the clients to know that, for example, the subtitle should be a combination of the request’s location, category name, and price.

A UI centric model focuses on what the user will see. The clients know how that field should look and where it appears, but they may have no idea what it actually means. It might still have some fields that they know the meaning of, for example some kind of object ID to use in future network requests, but most of the fields will be a black box to the clients.

Example of a UI centric model
An example of a UI centric model. Note that while the first line is clearly the customer’s name, the API field just calls it “title.” That way if we later decide to change what we display, it will be easy to do so on the server without client-side changes.

Issues with Business Centric Models

There are a few reasons why Thumbtack has moved towards UI centric models over business centric ones. If the clients are all getting business models, then each of them must create the logic to map those models to a UI. One example of where we had to do this is our messenger, where professionals and customers send messages back and forth.

An example of our messenger
An example of what our messenger looks like

Duplicated logic in our messenger includes figuring out if a given message is inbound or outbound, deciding which messages should be “bundled” together or displayed as a timestamp, and sorting out the combination of messages and other UI elements based on timestamp. In the best case scenario this meant we had the same code written in our iOS, Android, and website frontend repo. More practically, this meant there were inconsistencies across clients and unusual bugs related to how a specific client had implemented that logic.

This leads us into the second issue: we were putting more strain on our relatively resource constrained client engineers since any change required three different engineers to implement it (one per platform we support). Plus if there was a bug, it was often in the logic in the client code, which could lead to further complications. If we were lucky, it was an issue with the web frontend code because as soon as we fixed the bug, we could roll it out to all web users immediately. Otherwise, once we merged the native bug fix, we’d have to wait hours to days for Google or Apple to review our app. Then we had to wait even longer for users to update their app version (and we all know there will inevitably be those users who just won’t update).

The third issue came about from our attempts to modify the business model on the backend to work around client engineering constraints, which tended to introduce tech debt. A common scenario was that we’d see a specific UI element already existed and decide to reuse it to display different information. To make the change “backend only,” the backend would manipulate the model to get the client to display the UI we wanted without an actual client-side change. This is do-able (though not ideal) the first time you try this. After several similar iterations, it turned the code into a hard-to-reason-about mess. Without cross-referencing the backend and client code, it was impossible to tell what any given field did. This then makes future development even harder and slower.

By switching from a business centric model to a UI centric one, we’ve been able to reduce how much code we’ve had to write. Furthermore, we’ve can leverage the fact that we can deploy our backend immediately to make fast UI tweaks to all native clients. This doesn’t help with changes that must update the UI model schema, but it makes it much faster to update the UI for most users without relying on them updating our app. However, that isn’t to say that there weren’t any downsides to the change as well.

Issues with UI Centric Models

While we’ve had a great deal of success using UI centric models for views that require minor tweaks, we’ve found that this approach doesn’t work as well for views that are likely to dramatically change from iteration to iteration. If you’re switching the customer’s name with their profile image, a UI centric model won’t help you since you’ll have to update the schema to reflect this new information.

The other downside to UI centric models is that it requires the backend to be aware of how clients render the information they receive. This leads to a potential problem if we try to make the API overly flexible by allowing the backend to control every single element of the UI. An example of this might be having the backend send not just what the title text is, but also the font size, how much padding it should have, where in the layout it should be relative to other UI elements, etc. At this point, you’re simply inventing a new layout language and implementing it across the clients, which is likely to be more trouble than it’s worth. To this end, it’s important for engineers to collaborate closely with design to get a sense for what kind of changes they might or might not make in the future.

One other detail to keep in mind about the difference between a business vs UI centric model is how that affects collaboration and ownership between client and backend engineers. In a business centric model, ownership is fairly clearly defined. The backend makes sure the model accurately reflects the current state of the object, and the clients translate that information into a UI. With a UI centric model, those boundaries become more muddied. A backend engineer might need to consult with a client engineer to find out what field they need to change, or it might make more sense for client engineers to make the change in the backend themselves to reduce the coordination burden. In my experience at Thumbtack, this is less of a concern though. In both versions of our API, client engineers have been encouraged to gain some familiarity with the backend so that they’re able to make minor tweaks to the API data back. Similarly, with a business centric model, we’ve sometimes had to update the model based on how the client was using it rather than the object’s actual state to quickly roll out fixes to bad bugs without going through the native release cycle.

While it’s not always the case that a UI centric model will work better than a business centric one, we’ve had a lot of success with this approach. Furthermore, we’ve gotten better at thinking about how we might change our layout to better inform how we structure our models at the right level of specificity. For us, this largely means the backend has control over whether certain UI elements are visible, what the text says, and occasionally what color something should be. The majority of the other details like where exactly the UI elements are, what font size is being used, etc., the clients themselves are able to determine. We’ve also leveraged our design system to create common UI models that map to existing UI components. One example of this is our CTA model, which defines what text shows up on a button and some data the clients log if the user clicks on the button. So overall, moving to a UI centric model has allowed us to reduce the amount of code written, roll out changes to all users much more quickly, and develop new features faster.

If you’re interested in seeing some of the benefits of a UI centric model in action, come join us!

About Thumbtack

​​Thumbtack is a technology leader building the modern home management platform. Through the Thumbtack app, homeowners can effortlessly manage their homes — confidently knowing what to do, when to do it, and who to hire. Bringing the $500 billion home services industry online, Thumbtack empowers millions of homeowners to fix, maintain, and improve their most valuable asset. The company is backed by Sequoia Capital, Tiger Global Management, Javelin Venture Partners, Baillie Gifford, and CapitalG, among others.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store