tovarchristian21

tovarchristian21

Image Processing API Architecture

Hello everyone, I will start an image processing API in elixir that will have 2 main functionalities. The 1st functionality is to simply upload images to an S3 bucket. The 2nd functionality is the critical one, since this api will be consumed by a Ruby app for exhibiting several of these digital assets in different sizes and applying different transformations. My main concern is not the dependency that will process the images in Elixir, but instead is the architecture behind the api. The ruby app will be constantly fetching the images from S3 via the elixir app, I’ve been researching several technologies, and one that caught my attention was Broadway. I’ve used gen stage before, however I’m not sure if Broadway is exactly what I’ll need, how can I now that my system can handle all of those requests? that is one of my main concerns. If you guys have any suggestions or tips in order to achieve what I’ve mentioned, I appreciate it.

Most Liked

drl123

drl123

There are a few SAS offerings out there that do something similar (https://www.imgix.com/ is another one). The advantage is that they take care of supporting all of the new image types that come out (HEIC/HEIF, etc.) and you can focus on your core business logic. All depends what kind of ‘transformations’ you are doing and if you need the Exif data maintained/updated in the images after modification (I think Imagizer strips the Exif out by default). If you can live with the limitations of these SAS offerings, you may not even need the second app since they’d be doing the hard work…it would essentially just become an asset server.

Another benefit of Cloudfront is that the cache gets copies stored geographically close to the end users, so it improves their page load times, even if your api has only one availability zone.

Without knowing your entire use model, not sure if Broadway, GenStage or even Flow would actually solve your bandwidth problem or not. If the end users expect the image to be served right away, back-pressure on the asset delivery isn’t the greatest solution and you’ll need to build a queuing or retry system in the consuming app to deal with that back-pressure/delay that the Elixir server would be applying. If this is the case, and you actually have a throughput problem, you might look at ways to alleviate the bottleneck before adding a lot of overhead in managing the back-pressure on both sides.

polypush135

polypush135

So I’ve really been kicking this idea around for sometime.

I know this maybe not the ideal solution for you, but I’m activity working to learn rust so I can make a web assembly app that will scale the images client side and then I will have my client side app directly upload them via signed urls to s3. I think cost alone will make this a much more effective solution long term.

Photon: A WebAssembly Image Processing Library looks promising

drl123

drl123

Yes I’ve used this before and it performed quite well. If the files are really large, you may need to scale them down and then apply the transforms to the resized image if it is taking too long. If you find you need more than one instance, you just set up a load-balancer with multiple EC2’s behind it and auto-scale them. There’s an AMI for Imagizer in the AWS marketplace and you spin up an EC2 instance using it, then just pass query string params for the transforms. I believe Imagizer’s documentation explains all of the setup…been a while since I looked at it last (and I wasn’t involved in the initial set up either).

We actually used it without any middle app to do transforms right from the JS front-end of the app. In that case, the main api app only managed the pre-signed URLs for upload and the access keys for reading and Imagizer did the rest of the hard work.

Cloudfronting what is a common request eliminates much of the load from the main app freeing up the resources for the rest of the business logic. This also means you don’t have to store the same image in multiple sizes…the other sizes are just transforms and just pull from the cache, falling back to a new request only if they’ve expired, which just causes them to be re-cached. It’s pretty efficient.

Cloudfront is both super cheap, and super performant for the end user because it keeps copies geographically close to them, so time to glass is kept to a minimum (way faster than trying to do this on the fly, even with parallel transforms going on).

Technically, you could even use infrequent access instead of standard S3 with the CF caching and save on your storage costs too.

Again, it all depends on your application and performance needs. For our use case, it worked extremely well and was nearly maintenance free. The only time we had to touch the mechanism was when a new version of the AMI came out…otherwise, it just worked. Depending upon your request volumes (and keep in mind that CF helps keep that minimal after initial caching) you could also use their SAS offering and not have to deal with setting up the EC2 instances. With our volumes, EC2 was a cheaper solution, but you will need to evaluate that for yourself.

Hope this was helpful.

Where Next?

Popular in Discussions Top

andre1sk
A big advantage to Elixir is all the distributed goodness but for many applications running on multiple nodes having integrated Etcd, Zoo...
New
laiboonh
Hi all, I am trying to convince my team to use liveview over the current react. What are some of the points where one should consider us...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
New
chuck
Let me start by stating an assumption: Phoenix is a great approach to building REST APIs. There are many reasons for this, but I will ass...
New
nunobernardes99
Hi there Elixir friends :vulcan_salute: In a recent task I was on, I needed to check in two dates which of them is the maximum and which...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
und0ck3d
Hello everyone! A few days ago I’ve created a topic here about how people were creating CMSs with Elixir and Phoenix. I’ve been studying...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
AstonJ
If so I (and hopefully others!) might have some tips for you :slight_smile: But first, please say which area you’re finding most challen...
New

Other popular topics Top

chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New

We're in Beta

About us Mission Statement