Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: What are your experiences with using Starlette or FastAPI in production?
19 points by larrykubin on April 4, 2020 | hide | past | favorite | 11 comments
I'm currently evaluating Python frameworks for a new project. I've built a number of applications with Flask / Django over the years, but also recently discovered FastAPI, which is built on Starlette. I tried it out for a small hobby app locally and enjoyed the experience so far. I liked how you could define types with Pydantic, the dependency injection, and how it seemed a little easier to bootstrap and form a project structure vs. flask. The auto API docs are great as well. Also the FastAPI documentation itself seemed very thorough and had great examples for authentication, docker images, boilerplates, etc. The project and docs feel mature.

That said, I don't see as much written about FastAPI and Starlette. I want to recommend it for a major project. Is there a large community around Starlette/FastAPI? Have you used it for large mission critical projects with many users? Would love to hear more about real world usage.

Here's some extra background that might help understanding where they come from.

The creator of Django-Rest-Framework, Tom Christie, created a new API framework with what he thought would be the best approach for building APIs in modern Python. It was called APIStar.

APIStar had to deal with some complexities underneath like supporting WSGI (the same used by Flask and Django) and ASGI, the new standard, etc. So, at some point, Tom decided that a new approach was needed. So, he created a new framework/toolkit form scratch, based on ASGI, called Starlette. The server part of APIStar was deprecated and from then on APIStar was only a set of tools for OpenAPI validation.

Starlette was made to be a minimal micro-framework and toolkit at the same time, so that other tools could be built on top of it, but providing a very solid foundation, and the best performance available in Python, on par with NodeJS and Go.

Then, FastAPI was created on top of Starlette, inheriting a lot of the ideas form APIStar (that actually come from even before, with Hug) and updating/improving them, to use standard Python type hints, dependency injection, OpenAPI with docs by default, etc.

About community, you can check the FastAPI Gitter chat, it has a lot of people and there's always someone asking questions and many great community members helping too.

And yeah, FastAPI is being used for what could be called major projects, e.g. Microsoft APIs for Windows (among others).

Disclaimer: I created FastAPI :)

Hey, I ended up creating a screencast of my experience building a small app with FastAPI in case you want to include it in the docs anywhere. Been trying to share more tutorials / videos this year. Will let you know when I make something bigger with this.


Thanks for the background and awesome work on this, excited about using it.

A past client of mine was using one of these relatively obscure frameworks. It's fine when it works (though I feel like the developer experience is much worse than let's say Django REST Framework) but when it breaks good luck figuring it out.

My recommendation is to just go with Django until the performance becomes a problem and it can't be solved by a "boring" solution such as throwing more hardware at it. Even after that, you can still squeeze out extra performance by using Serpy serialisers instead of the built-in DRF ones. Finally, if performance is still a problem then you could potentially use one of these frameworks. In most cases though, your underlying data store will be the bottleneck.

In my client's case, we were looking at a couple requests per second maximum, so they unnecessarily spent extra time learning and using an obscure framework without actually benefiting from it in any way.

> I feel like the developer experience is much worse than let's say Django REST Framework

Give FastAPI a try! You probably have DRF-Stockholm-syndrome like many do. The joy of having all pieces fit right in and be understandable and have validation auto-generated from type annotations (if you choose to) is a-f-mazing!

After using DRF quite a lot for quite a while I can clearly self-diagnose myself as being abused by it - such ugly patterns you always end up coding around and fighting the framework everywhere...

Use Flask if you're afraid of Python async, there's probably good reasons to be, never had to debug it in production... but LIKING DRF?! I cannot fathom that, I mean, one can like Django itself, it's good for what it was built to do, but what abominations ppl built on top of it instead of starting from scratch... ugh!

I don't understand which parts of DRF you don't like, or why FastAPI is better.

In my case the reason I like DRF is because it handles most of the work for me - I do my best to make my APIs RESTful which means I expose the underlying data model whenever possible. DRF makes that easy and I only need to handle the authentication classes and hiding sensitive fields in the serialiser.

As an example, let's assume I have a User model in Django and I want the mobile app to be able to read and edit the user's profile (name, bio, etc). With DRF I just create a ModelSerializer for my User model, put it in a ViewSet with the appropriate permission classes (so write operations are only allowed on the currently logged in user) and call it a day.

With FastAPI, looking at their homepage, it seems like I have to implement every single HTTP method (GET, PUT and PATCH in this case) separately? I just don't see the point.

Maybe if you're looking to create an RPC-style API then I guess it could get in the way, but for REST APIs I don't see why this is better.

You're probably lucky to have that use-case.

Most problems I had where with:

(1) deeply nested tree-like objects updates - model serializers have limited support for nested updates, but it breaks down fast, if your frontend-exposed data looks more like trees than tables you'll be fighting it all the way

(2) REST semantics can only get you that far! You end up doing some form of domain-driven-design sooner or later and your verbs are no longer (just) create/read/update - you have "approve", "reject", "approve with comment", "flag for review", "restore to version 123" etc. REST is not CRUD, you can have REST semantics with only R from the default actions and everything else can be domain specific.

In general I prefer to (a) not expose to the API the actual backend's data model in all its gory complexity and (b) figure out what actions make sense for the application domain, drop the CRUD handcuffs.

Once these choices are made, which I now prefer to do early on, pre-emptively, something like DRF becomes pure-pain, 0% gain: I use nothing from it, and it's too dumb to autogenerate stuff like validation or to offer some structural patterns from which to hang code for things like sub-object permission checks or anything like that...

I agree with you on 1) and I'm not saying models and serialisers will always be the right choice. In certain cases custom serialisers will make sense and you will have to write code, but you'd be writing the same code with a framework such as FastAPI or Flask.

Regarding 2), REST will get you most of the way there, and depending on what "approval" means (does it trigger some process, or does it just change a flag in the database?) it might just be a PATCH "approved = true" on the RESTful endpoint, but when that's not the case you can indeed extend DRF ViewSets with custom actions.

I disagree on not exposing the data model; unless the model is really bad or needlessly complex, I think exposing the model is fine instead of "fabricating" a new model full of RPC-style endpoints. I've wasted way too much time in RPC-land where every little extra bit of data needed a change in some other microservice managed by another team with a convoluted deployment process meaning the change took a good part of the day, where as if they were just using REST I would've had the data to begin with. I don't think CRUD is handcuffs, at least the "R" part feels very valuable to me.

This discussion was really valuable to see.

I started off with FastAPI, and it got me off the ground really quickly without a lot of boilerplate, and my API was mostly read only, internal, I didn't even bother with authentication at this point. The prototype worked well.

But then I started to add in all the grown-up, boring stuff and realized would have to do a lot from scratch. Now porting it to Django/DRF and the stability feels really nice. I kinda wish I had just started with DRF now.

There is a package for DRF that adds automatic validation from type annotations: https://github.com/rsinger86/drf-typed-views (disclaimer: I'm the author)

Regarding other commentary on DRF: I wonder how many pain points result from trying to squeeze non-CRUD operations into DRF's ModelViewSet/ModelSerializer constructs? My company's approach has been to use that DRF magic for dumb CRUD resources and use plain function-based views for everything else, with the freedom to use Pydantic/Marshmallow/etc. This has made us very productive and I can't image having to write create/update/delete/get/list operations one at a time.

That said, I'm sure there are use cases that DRF isn't suited for and I would definitely look at FastAPI for new projects.

FastAPI is awesome and dev experience is much much better than the heavy not-really-built-for-this-use-case Django + DRF mostruosity. But what I'm using it for is very low load... more like "internal use app" level of traffic. Can't say much about performance yet.

But it's lovely and a pleasure to work with, most developer friendly thing I've ever touched lately!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact