Going serverless: Zappa vs Chalice 2018
I had the need to create a tiny API recently and decided to finally try out AWS Lambda. It's probably the leader in the "serverless" movement, which really just means someone else manages your servers for you.
Normally, I'd have had to stand up an EC2 instance, or host a docker container, then build the whole server infrastructure (web server, backend, etc) and monitoring (did the webserver die? backend get stuck?). The idea with serverless is you write the functions you want called and when, and the rest is done for you. Including scaling, if you want. Since I prefer python for most things, the two frameworks I looked at are Zappa and Chalice.
Positive: More Mature
Zappa was released 6 months before Chalice. In this extra bit of time, it gained a lot of users and mind-share.
Positive: Seamlessly supports flask and django
If you're already using Flask or Django, this can be really handy. However, not all extensions "just work" and you'll likely be modifying your code to leverage lambda features anyway.
Positive: Supports easy asynchronous background tasks
This can be handy for starting a longer running process in the background and returning faster to the client. At the same time, there are other somewhat easy workarounds, like using a messaging queue.
Positive: Seamless support for 50M+ files
A basic hello world lambda package is about 6M. It doesn't take a lot of code to hit the 50M lambda zip file limit. You don't need to worry with zappa, it seemlessly puts your zip file in S3 and lazy loads things from it. One downside is it also does this, even if your zip is less than 50M, making initial setup more complex.
Positive: Large community
Tons of people have tons of questions and answers on all sorts of topics. This is a huge plus.
Negative: Somewhat heavy
Being a more robust framework, it does feel a little heavy. It has a lot of python dependencies, and for a simple API can feel like overkill.
Negative: Lambda somewhat treated as a bolt-on
Zappa is trying to simultaneously appease two goals: Flask/Django integration and lambda integration. It delivers on both, but not without some compromises. One of the big ones in my mind is the fact that you can only enable authorizations at the API level, not the function level. So, if you have an API protected by signed requests, you can't have one function that is not protected, or protected by a different method. Sure, you can argue such functions maybe should belong in a different API, but that opens a whole new can of worms.
Negative: Inexact IAM permissions
Configuring Zappa IAM permissions is not an exact science. This thread speaks volumes, as you can see the exact IAM permissions needed to make Zappa work are not defined yet. Translation: trial and error or be overly permissive.
Positive: Supports per-function authorization
For my use case, this was a deciding factor. I wanted one open function, and the rest protected. I couldn't do it with Zappa.
Positive: closer integration with lambda
Chalice only exists to make APIs for lambda. This singular focus means it tracks closer to how lambda works and what it supports, instead of a weird middle-ground of not-quite-flask and not-quite-lambda.
Positive: written by Amazon
Since they run lambda, this is a plus.
Postive: light weight
Far fewer dependencies, less configuration, easier (and defined) IAM setup.
Negative: Smaller community
Not nearly as many people are using Chalice. It's harder to find good examples and real-world anecdotes.
Negative: Can't import from Flask or Django
If you already have a Flask or Django API, you'll have to transpose it into the similar, but not exact, Chalice API.
Negative: Written by Amazon
Let's face it, a lot of Amazon's tools are sometimes rough. They are usually poorly documented, rough around the edges, but get the job done.
Neither option is perfect, and both come with some large trade-offs.
Choose Chalice if:
- you specifically need something only Chalice can do
- are just starting a new API from scratch
- just want to keep it simple
Choose Zappa if:
- you suspect your API will be somewhat large
- already have an API in Flask or Django
- your API is core to your product