At HelloFresh, My Deliveries is one of the screens our customers interact the most with. That's where they review what's coming up in the next weeks and select their recipes and add-ons. Unfortunately we were getting a lot of complaints about it, mostly related to loading times. While I was writing the menu service I got an idea to improve performance. Little did I know it would take 4 months to complete… That's the journey I'm about to tell you.

At the time, menus were being served by our API monolith, and they were huge monsters, worth 200Ko of compressed data. That's because they were featuring full-blow recipes, which really were the real monsters. As you can guess they were also very expensive to compute, also because a number of extraneous properties were injected to the already massive documents. Response time was about 600ms. Consuming them was equally expensive, decoding JSON has its cost too, especially on low-power devices.

If we look closely at the My Deliveries screen, there's not much recipe properties being used for display.

My Deliveries

I started listing the properties actually being used on a Confluence page and I involved all stakeholders in the process. We came up with a final list that was working for everybody. We called this a preview recipe.

averageRating: float
cuisines: Cuisine[]
difficulty: int
headline: string
id: string
imageLink: string
label: Label
name: string
nutrition: NutritionAmount[]
prepTime: string
slug: string
tags: Tag[]
websiteUrl: string

Luckily most clients could use this preview recipes, and those who could not could switch easily to the menus service, since their payload are strictly compatible. Still, I didn't want to repeat the mistake of the API monolith and I updated the menus service to serve "preview recipes" by default. For convenience, I provided a query parameter for clients who really needed full-blown recipes.

We listed all the clients and pieces of code using menus and started the migration from the API monolith to the menu service.

The migration

The migration took a lot of time and suffered multiple setbacks, mainly because the readiness of the mobile applications was underestimated, and it took a long time to release new builds and get users up-to-date. I also had to push some product owners to prioritize the migration, reminding everyone that improving the customer experience is paramount, and that the "my deliveries" screen is crucial.

After 4 months of hard work it was time to release the final PR that would switch on preview recipes in the API monolith.

Release time

The release was a huge success. Response time was divided by 3 and response size was divided by 40! Our frontend chapter lead was very happy :)

A graph representing menu timings
The response time is devided by 3
A message from Slack
A happy frontend chapter lead

Lessons learned

  • Communication is key.
  • Keeping stakeholders involved is key.
  • Accurate software audit is key.
  • Trust… but double check.
  • Code without owner is a mystery.
  • Deprecated code is eventually a pain.
  • Serializing with JMS is expensive.

We also discovered that all the extraneous information injected in menus by the API monolith were only required by My Deliveries. The migration to the menu service brought tremendous performance boots throughout the system.