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 complains 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.

It's too big!

At the time, menus were being served by our 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.

Do we need all that!?

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

My Delivery screen

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 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 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 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 :)

Smaller menu timings

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 hugely expensive.

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