Music in the streaming era doesn’t exist alone, it is coupled with images; album arts, playlist cover arts, the colorful image you see in your curated mix and everything in that space. We are a music streaming company, and image processing lies in the core of our work. Back in 2017 the engineering team decided to explore solutions to our image processing needs and that led us to one of the dozen solutions available on the web.
However, our needs grew in parallel with the size of the company and soon enough we were billed more than we ever anticipated. Cutting costs is always a priority which pushed us to create our own service and later on realizing the big wins we can achieve utilizing it as a design automation tool. What started off as a cutting cost project became one of the pillars in the creative and marketing pipeline at Anghami.
That’s a hefty bill!
We initially adopted a popular online solution that allowed us to deliver, render and create images with ease. Soon enough, we were posting a hefty bill, much more than we expected. Discussions were made on a possible solution and despite multiple optimizations the bill was still not justifiable enough. We decided that the best way to move forward is to create an in-house solution that would mimic the behavior of the aforementioned solution without losing the functionality.
In comes Goya, our in-house service that serves images from S3 and exposes an API to create different images. The big wins were clear early on as our bill dropped down by 60% limited to the cost of hosting the service on EC2 and the network costs.
Nobody likes labor work
The service was initially designed with migration in mind, nobody wants to go through tens of classes to change snippets of code here and there. The solution was simple, expose an API that mimics the same endpoints and query parameters as the old service thus minimizing any changes that needed to be done in the different codebases.
One of the first uses of Goya was to provide a portal to create cover arts for our featured playlists. This process usually required collaboration between designers and curators to craft multiple images per week.
A major win for us came at the end of 2019 where we usually do an End of Year campaign. The campaign involves images containing unique statistics about users which are usually created by designers and engineers hand-in-hand. Designers would provide different customizations of a template and engineers would insert the user data in these templates using FFmpeg and ImageMagick. Automating this process became possible by creating Dynamic Presets which are customizable template URLs that take in query parameters containing user data, colors, language, shape and size, render the image on the fly and serve it with compressed quality. In comparison with 2018, hundreds of hours were saved in the process of EOY preparation.
Open the hood
The rendering service sits behind two content delivery networks starting with Akamai due to its extended availability in the MENA region with PoPs distributed across the whole network followed by a CloudFront distribution. Having CloudFront allows us to reduce the outbound traffic cost significantly since traffic from EC2 is free. Having two CloudFront pops means we only need to compute the image twice instead of triggering a render for each Akamai PoP which reduces the compute cost and protects EC2 instances from unnecessary request bursts when new images are published.
If an image is served using an asset ID, which points to locations of cover arts, RDS and Redis are used to fetch and cache file locations.
We utilized Lumen to write the service in addition to utilizing Intervention Image, an open source PHP image handling and manipulation library.