At HelloFresh, My Deliveries is one of the screens our customers interact the most with. That is where they review what is 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 is 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 200KB of compressed data. That is because they were featuring full-blow recipes, which really were the real monsters. As you can guess, they were also costly to compute, also because a number of extraneous properties were injected to the already massive documents. The response time was about 600 ms. 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 are few recipe properties being used for display.
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 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 these preview recipes, and those who could not could switch easily to the menu service, since their payloads are strictly compatible. Still, I didn't want to repeat the mistake of the API monolith, and I updated the menu 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 thrilled :)
Lessons learned
- Communication is key.
- Keeping stakeholders involved is key.
- Accurate software audit is key.
- Trust… but double-check.
- Code without an 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 was only required by My Deliveries. The migration to the menu service brought tremendous performance boots throughout the system.