Full-featured web frameworks are great, but sometimes living closer to the network layer
is exactly the thing you need. This week, you'll meet Kurt Griffiths and John Varbenak,
who work on the Falcon Web Framework. It's a bare-metal Python web API framework for building
very fast application backends and microservices. How bare-metal? Well, other frameworks like the
HUG REST framework are even built upon Falcon. This is Talk Python to Me, episode 129, recorded
July 17, 2017.
Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the
ecosystem, and the personalities. This is your host, Michael Kennedy. Follow me on Twitter,
where I'm @mkennedy. Keep up with the show and listen to past episodes at talkpython.fm,
and follow the show on Twitter via at talkpython. This episode is brought to you by Linode and
Rollbar. That's right. Welcome to Linode, who has joined Talk Python to Me as a major sponsor.
Be sure to check out what both of them are offering during their segments. It really helps support
the show. Kurt, John, welcome to Talk Python.
Hi. Thanks for having us.
Yeah. It's great to have you guys here. I love talking about web frameworks, and yours looks
very, very interesting. So I'm super excited to share it with all the listeners. But before
we do, let's start with your stories. Kurt, how did you get into programming Python?
Well, so just programming in general, I got started way back in the day in sixth grade. I was in
my math class, and they had a, I think it was probably a Commodore or a Pet, one of those old
crafty machines. And someone, one of my classmates just came in one day and said, hey, check this
out. And he brought up the basic terminal, and he typed in this little program. And all
it did was convert dollars to, I think it was to yen. Nothing fancy, but like I'd never seen
someone program before like that. And they just kind of sparked my interest. And I thought,
that's so cool. You can like type incantations into the keyboard and the computer will do something
for you. So that's kind of how I got started.
Yeah, that's really nice. And it probably didn't seem like unachieable. You're like, how did you
do that? Oh, that's all? Well, that seems pretty easy. I could do this, right?
Yeah, exactly. It was very approachable. And I think probably a lot of people got introduced
to that, to computing. So this was back before a lot of people had computers at home. And
some of their first interactions with them were like at school. So yeah, I went home and I did
a little research. I found out that not long after that, my dad brought home an old surplus
IBM XT from work. And I found out it had basic on it. And so I saved up my allowance for a few months.
And much to the astonishment of my sister, thought I was wasting all my money. I spent it all on a
programming book. And then kind of the rest is history.
That's awesome. What was the first language? What was that book on?
Yeah, basic was first language. I went on from that to, I think it was C++. And I've kind of,
I've learned a lot of languages on the way. So I've actually been doing Python probably for about
about five years now.
Nice. How'd you get introduced to Python?
So that was after I came on board to Rackspace. And we were doing some projects there. And we'll
probably talk about this a little bit later. But I was actually doing a lot of C++ at the time. And
we had done some C++ on the server, but that's not very fun, I have to admit. So we were looking for
something a little more friendly for that environment, something a little more easier to work with.
And kind of settled on Python. A lot of other people were using Python at Rackspace. And so it was kind
of a natural choice. And I started doing some Python things.
Yeah, yeah, that's cool. Did you miss the curly braces? And the semicolons?
It took some getting used to that I must admit. But now I have the opposite problem. I go back and I
keep forgetting the curly braces.
Yeah, I hear you. I've made a new rule for myself. I'm going to try to write JavaScript with no curly
braces. If it's willing to add it, I'm willing to not write it.
Yeah, there you go.
How about you, John?
Yeah, so I actually got started programming whenever I was a little kid. My father was an electrical
engineer for Cisco Systems. And whenever I was seven, he introduced me to DOS and BASIC. And
quickly kind of outgrew that and then ended up in Borland's Turbo C++. So that was my first taste of a
real language, I like to say.
Yeah, yeah. C++ is a good language.
Yeah, especially back in those days. It was, you know, the days of, you know, no stack overflow and
spending a bunch of time in the Barnes and Nobles or borders, you know, in the programming language aisle.
Back when you had to earn your knowledge?
Yes, yes.
That's right. So how'd you get to Python?
So interestingly enough, I've been getting involved in a lot of Linux work. This would have been, what,
2012-ish. And at the time, I was having to do a bunch of build scripts and whatnot in using Gradle.
And I kind of got really tired of doing a lot of that. And I was like, well, a lot of people use
Python. So I started getting interested in that just from a scripting perspective. And then I think it
was App Showdown or something or whatever it was called back then. And I thought, well, let's try to
write an app. And I think that was the worst Python I've ever written in my life. But it got me
very interested in it.
Oh, yeah. That's really, really cool. All right. So what do you guys do day to day? Kurt,
I'm guessing from the background, you might be at Rackspace right now?
Yep. So I've been at Rackspace about nine years. I'm actually going to be leaving pretty soon here
to kind of work on some startup ideas. So I've done a lot of stuff at Rackspace. Most recently,
I've been working on sort of, well, what we call managed security at Rackspace. So we provide a lot
security services for customers. We take vendor products and we kind of wrap them up and glue
them together and make them easier to use and provide a 24-7 SOC that's staffed by security
analysts that kind of watches our customers' servers, make sure that we kind of keep the
bad guys out. So I've been working in the security space probably for about three years now.
Yeah, that's really cool. So what kind of stuff can you guys do to keep hackers out? Like for me, I
make sure I patch my code straight away, you know, as soon as any security updates come out,
try to follow the best practices and stuff. But beyond like simple guidance, right? Like can you,
how do you detect these things?
Yeah. I mean, there's certainly just the basic stuff that you need to do, the patching,
et cetera, that you mentioned. The Center for Internet Security publishes a number of hardening
guidelines. A lot of people follow, especially if they need to get PCI compliance or something like
that. So you kind of do, you do your basics. Beyond that, the attackers have become so sophisticated
these days that like, it's really not when they're going to get in, but I mean, it's not really,
not really if they're going to get in, but when.
Not if, but when.
So, so that kind of falls into how do you monitor constantly? How do you react quickly
when you would detect an anomaly and you've got to get in there and diagnose it and find
out, well, maybe it's just, you know, you change something in your application. So it's fine.
It's just behaving a little differently. Sometimes maybe, yeah, someone's in there and you need
to kind of throw down the, the firewalls and, and get them out. So it's a combination of
kind of the hardening, the patching, but also the constant 24 seven vigilance and having a
response plan in place. So you can react quickly and resolve the issues.
Yeah. I'm sure you have some, pretty amazing stories, but let's stay focused on Falcon.
John, how about you? What do you do day to day?
So I actually work in a rack space managed security as well. I'm relatively new to the team.
I previously came from EMC and then previous to that, I actually was in a different part of rack
space. So kind of jumping around the industry a little bit.
You live in the cloud.
Yeah, pretty much. I think, a lot of what I do day to day is help, build some of the
utilities that we use internally to manage security. So helping in delivery of some of the, some of the
products and helping isolate what, and how we're, how we're using our tooling. So, yeah,
it sounds cool. Like I said, I'm sure you guys probably have awesome stories that would be really
fun to dig into, but let's talk about your web framework Falcon. It looks, looks really neat.
Kurt, you want to tell us what is Falcon?
Well, so just basically it's a little Python web framework for building microservices,
proxies, application backends, those sorts of things with a particular emphasis on, on low latency,
high scale use cases.
Yeah. So one of the ways you describe it as a bare metal Python web framework. So yeah,
that kind of gives you a sense, right? It's not, it's not Django with its admin backend and,
and that it's, it's something way more low level and closer to the network, right?
Yeah, definitely. So it's a relatively thin layer on top of whiskey. so there's not a lot between
you and your web server. And it also tries to kind of embrace HTTP versus paving over it. So you have
direct access to everything that's going on.
Yeah, that's cool. Headers, requests, response, all of that codes, all those things are super
natural in there. Yeah. Yeah. So people listening to whiskey, web service gateway interface,
like the standard that almost every Python web framework implements to be a Python web framework
and plug into the high performance web servers. So you have a nice little, problem for people to
solve math problem on your homepage. You said you've been unburdening cloud apps for over 4.5,
three times 10 to the next second centuries. So you've been around about 4.5 years or so. Is that right?
Yeah, that's about right. I kind of stole that from ours. Technica used to have a little thing in,
in kind of the early days when they're getting started, they used to have a little thing on their
website. so I have to give them credit for that. Yeah, it's nice. Yeah. So why don't you guys
both tell me, Johnny first, what's your relationship to the product? Like, or to the project? Like,
did you both start it together? Someone, one of you started first, I'll come along later.
I got involved in Falcon a little bit further into its, into its history. I suppose, my initial
use was purely as a user. I, was using it to, to solve several scaling problems from just like a
general sense from a performance standpoint. But overall, I kind of, what attracted me to Falcon was
the kind of non-opinionated ideas, being able to have like a flexible base that I could build upon
and, you know, reuse over and over almost like a framework for frameworks, if that sort of makes
sense. Yeah. That is interesting. I think there's people who learn web development or do web development
are kind of in two camps. They either like all this flexibility and like, I'm going to pick this
ORM or this data access layer and this caching layer. I'm going to plug this together like that.
Or they want just, it's kind of slotted together like this style or Django, right?
The interesting thing about Falcon is that it kind of, in some ways, like a lot of frameworks are very,
have a very opinionated way of approaching things, which is, you know, both good and bad. I think,
Kurt and I like to talk about how Falcon is kind of in the middle of a spectrum of frameworks. You know,
all of them have different and important purposes, but yeah, some, in some cases, it depends on your,
either your own personal opinions or, or the problem you're trying to solve. But in the case of
Falcon, it just seemed like to, to jive with the way that I thought, the way that I approached problems.
And fast forward a couple years later, then became a maintainer. So yeah, that's cool.
Wait a minute. I'm working on, I'm creating this thing. I was just using it. What's going on here?
How'd I get here?
Yeah, exactly.
So Kurt, what was the original idea behind creating Falcon?
Well, that's an interesting story. So Falcon was actually based on an experimental framework
that I had developed four plus years ago. So at the time my team and I were tasked with building a cloud
backup product for Rackspace. And the way this would work is you would have these headless agents that
would sit on the cloud servers. They would do the heavy lifting, the backup encryption,
uploading to cloud files, which is Rackspace's version of OpenStack Swift. And you need some way to kind of
command and control the agent, right? So it needed to be able to talk back to this sort of monolithic
web application that had the control panel there, had some of the control logic, the settings, you know,
what you should back up, et cetera, how often you should do it. So we needed some simple messaging
mechanism for those two things to talk, the agent and the control plane.
So we started looking at some different ways to do that based on some previous experience.
We were kind of biased towards using the REST architectural style for that messaging service.
As I mentioned earlier, so I had played around with Node, JS, but that wasn't really a, it was still pretty new at the
time and not a lot of people were using it at Rackspace. But Python seemed to be more of a natural fit.
So I started just kind of looking around, you know, I'm kind of a firm believer in using the best tool for the job.
I just kind of looked at some of the different frameworks. Flask seemed kind of like a natural fit.
It's a little bit lighter weight than Django. Looked like it might be a good way to go.
So I just kind of built like a very basic kind of hello world app, like as you do, and just benchmarked it.
So the thing with this, we had some very stringent latency requirements, because one of the things that you would do
through the control panel is actually go browse your remote machines, their file systems and choose what you want to back up, right?
And so that message passing had to be semi real time. We wanted it to be as responsive as possible.
So I kind of had an idea of a budget of response time. I don't remember exactly. It was certainly under 200 milliseconds, probably more
120, around there. Ideally, we want to get it down.
Does that count ping time?
Yes, overall.
So you need it under 200 milliseconds for it to feel real time. That's just the nature of humans, which means that your app, you don't have much left over for just for your app to turn around the request.
Honestly, at the end of the day, you have like 40, 30, 20 milliseconds to turn around a request, because a lot of the time is just eaten up with traversing the internet. So yeah, so I didn't have a big budget for the latency there.
And I benchmarked just a simple Falcon app. And it was much higher than I expected. I honestly, I don't recall the exact time. But I thought, you know, that's kind of weird. Let me just try just a straight up raw whiskey app.
You know, so I looked up the PEP 333 and wrote up just a simple, simple app there that didn't do anything. And there was actually a huge gap between that, you know, the response time there, and just with like a Falcon hello app. And I thought, that's weird. You know, what is Falcon doing? I mean, what is, what is, it's taking so long, right?
I have to kind of confess a sin here. I used to do a lot of Ruby as well, Ruby on Rails stuff. And I remember this Sinatra framework, right, which is kind of one of the early projects to explore this micro framework concept. So I did the same thing over there. I did a basic, like, just raw rack app. And then I benchmarked Sinatra. And just the difference between those wasn't actually that great.
And so I just had the hypothesis that, you know, there's probably stuff that's, I could probably make a thinner framework than Flask that would give me enough, enough to work with it. I don't have to just code directly to the whiskey interface, but it's still, you know, fast enough for my, for my needs.
Right. You just need a few abstractions. You need body, you need the verb, you need the headers, and you need JSON serialization or something like that, right?
Exactly. So it just started out very simple, kind of as this experiment, very pragmatic. And I ended up building this little framework, and we put that service into production, and it worked really well for us. And so I decided we probably should make this real. And so we started the Falcon Project, started inviting people from the community to try it out and contribute. And then that's where, that's kind of where it came from.
Yeah. Okay, that makes a lot of sense. Definitely in the benchmarks, which we'll talk about performance later. It's faster than many of the other sort of well-known frameworks.
Yeah, definitely. And kind of going back to what John was saying, it's there when you need it. Not everybody needs it. So it just kind of depends on what your use case is.
Yeah, for sure. So John, maybe this is an interesting time to do like a compare and contrast. What's this framework? Like, how is it different and special than let's say Flask, Django, Pyramid, these types of frameworks?
Inherently, the more pragmatic approach, I believe, for Falcon is kind of the benefit. But to like what I was saying earlier, a lot of this does tend to be very much of a spectrum and kind of a part of the, you can almost think of the wider community of frameworks.
The direct benefits. Yes, you've got performance, but sometimes performance is not always the most important thing. I heard someone say once, and I firmly believe this, that in a lot of cases, time to market is more important. So you can have the most performant app in the world. But if you don't get the job done, then...
We'd all just be optimizing our stuff in assembly and making it go really fast.
Yeah.
I think, you know, there are some interesting differences. A lot of them do come around the kind of more either heavier or opinionated type, say, almost workflows.
The benefit that Falcon has given me personally, and one of the reasons I got very interested into it, is that especially when you're building internal tooling, often cases you need a certain level of flexibility that oftentimes opinionated frameworks don't give you.
So, like, they might be great for the top, you know, for like 80% of your work, and then it's a real burden to try to get through.
It doesn't mean that those frameworks aren't any, you know, worse or, you know, better. It's just a different tool for the job. So, to like what Kurt was saying, trying to focus on the right tool.
Yeah, absolutely.
What we've seen in talking with users is it's really become sort of a complementary framework to what people are doing. You'll have someone who has a large sort of monolithic Django app, and they have a really hot endpoint.
Maybe they're using Django REST framework, which is a great framework, but for this one endpoint, it's just killing their servers.
So, they carve that piece out, write it in Falcon. It lets them make the performance trade-offs that they want to make, and then, you know, they keep the rest in Django, and then they are able to partition that one piece off into a microservice, and that works well for people.
So, that's just one example of how it works alongside these other frameworks.
Yeah, that's a much better answer than saying, let's rewrite it and go. Let's rewrite it and C++. Let's rewrite it and, you know, name your other language and technology that has its own problems, right?
I think that's something very important to kind of go along with that. A lot of people, they do focus on those initial numbers.
Those numbers may look great, but, you know, real-world numbers are often much different than benchmark numbers.
And at the end of the day, a lot of this, especially in today's world, it's about how you can scale your app after the fact.
Like, you may only have a couple thousand requests a second, you know, out of the gate.
But whether or not you can, you've architected your system or your application to be able to scale to 100,000 or a million or whatever, that's usually the most important.
Because in this day and age, hardware is scalable.
Yeah, for sure.
And you definitely, you know, the benchmarks, they're often doing something very, very lightweight inside, like reading a value off the query string and returning it back as JSON or something.
And I think maybe the way to think of it is more like this is the overhead this framework adds to your app.
But that's not your app.
You know what I mean?
Like, your app is actually the talking to the database, the logic, this other service it calls, et cetera, et cetera, right?
Yeah.
I mean, if you recall the little story I told, I mean, kind of the core idea around Falcon is our promise to you is we will remove the bottleneck in the framework.
Your performance bottleneck will not be in the framework.
Everything outside of that is kind of up to you, right?
And it depends on all the things you're doing.
That's still your problem, yeah.
Yeah.
So, but at least you don't have to worry about that piece.
Yeah, it's really cool.
I definitely want to talk a lot about the performance, but a little bit later.
Falcon is mostly for building APIs, if I understand it right.
Is it possible to build like Jinja 2 or Chameleon-based UI type things, or is it really just focused on APIs?
You can.
I know several of our users have actually asked how to do these types of things, and it's actually not that hard to plug in a Jinja 2 rendering system into,
into your resources for Falcon.
Is it really well designed for that?
Not really.
You could easily build something around Falcon to do it.
Often cases, I think the majority of our use cases are mainly around APIs, but it doesn't mean you couldn't.
Sure.
And I think it's kind of cool to have a framework focused only on APIs, because you know what?
It's really probably super good at that, right?
Compared to trying to fit it into all these other models.
One of the things that I was talking with the user, this was quite a ways ago, maybe in December,
and they were actually building effectively a little ORM on top of Falcon, just to kind of give you an idea of what the scope of how much somebody was able to change it,
which is, you know, that's awesome that they're able to do that.
I would imagine it would be a little bit more work than what people would often want to do.
Maybe another framework is a little bit more well-suited for it, but in their case, they wanted the flexibility and control.
Sure.
Yeah, so probably people that would do that sort of thing are kind of your control freaks, right?
They want to tweak everything.
Control freaks in the developer space, never.
We're happy to accommodate them.
Yeah, that's cool.
We want to do it.
This portion of Talk Python To Me is brought to you by Linode.
Are you looking for bulletproof hosting that is fast, simple, and incredibly affordable?
Look past that bookstore and check out Linode at talkpython.fm/Linode.
That's L-I-N-O-D-E.
Plans start at just $5 a month for a dedicated server with a gig of RAM.
They have 10 data centers across the globe, so no matter where you are, there's a data center near you.
Whether you want to run your Python web app, host a private Git server, or even a file server,
you'll get native SSDs on all the machines, a 40 gigabit network, 24-7 friendly support,
even on holidays, and a seven-day money-back guarantee.
Want a dedicated server for free for the next four months?
Use the coupon code python17 at talkpython.fm/Linode.
You guys had said that it's almost like a meta framework in some sense.
It's like low enough that you could actually build other frameworks kind of on top of it in a sense.
Does that sort of land in that space, this example?
Yeah, definitely.
We've seen a couple people do it.
Hug is probably one of the better known frameworks that's actually built on top of Falcon.
Interesting.
Hug is built on top of Falcon.
I was going to ask you about Hug and Django REST Framework and API Star.
Those three, well, API Star and Hug feel like the newcomers that are also trying to be API-focused only,
whereas Django REST Framework is more extending Django than kind of being a new thing, I think.
Yeah, I mean, I think the Django REST Framework is trying to just be an easy on-ramp to APIs when you're already doing your work in Django.
So it's a natural place there.
I think Tom's done some good work with that.
And, you know, you look at Hug, API Star, those sorts of things.
They're trying to kind of ease the burden of API development.
When you kind of do that, you necessarily have to be more opinionated.
We've mentioned this earlier, Falcon tries to be a little more low-level, less opinionated.
But you can certainly build these kinds of things on top of it.
Yeah, that's really cool, actually.
And it's interesting to hear about the Hug relationship.
So speaking of the philosophy, you had three basic driving points for your philosophy to be light, fast, and explicit, right?
The light, we've kind of touched on a little bit, being fairly low-level.
But there's a couple things that we haven't mentioned, some of the benefits that gives you.
One is that you have a smaller code base, so it's easier to make a reliable framework.
When something blows up, it's easy, somewhat straightforward to find the problem and fix it quickly, which becomes very important in large-scale deployments.
When you're serving many, many thousands of requests, you have hundreds of servers, you need to be able to diagnose problems very quickly.
So that helps as well.
And it also helps just optimize it.
It makes it easier to do that as well.
Yeah.
One of the ways to optimize code to make it go really fast is to just not run code.
That's right.
Right.
This part would be slow.
Let's just not do that in our framework.
Do less work.
Yeah.
That's the name of the game.
What else?
So fast, and we touched on that a bit before as well.
We try to be one of the fastest frameworks.
I don't think we necessarily claim to be the fastest framework for all benchmarks in all scenarios,
but we try to be up there at the top.
And again, make sure that you don't have to worry about, you don't have to spend time looking for the bottleneck in the framework.
You are in control of making those performance tradeoffs outside of that piece.
Yeah, for sure.
And the third was explicit, right?
Like, keep the magic out.
You can do a lot of clever things with thread local storage and inversion of control and things like that.
I mean, we do a little bit of IOC, but we try to make it painfully obvious, like, where the data is coming from, where it's going, how to set the data, all those sorts of things.
Because again, especially in large-scale deployments, when you're trying to debug an issue, you don't want it to be doing something surprising.
Yeah, absolutely.
The more obvious, the better there.
So kind of the opposite of Ruby on Rails or these other frameworks that have lots of conventions and stuff just happening, you kind of got to know it, right?
Like anything, there's a tradeoff.
Like, you get a lot of power from that, but there is kind of a lot of magic and kind of a steep learning curve there.
Sure. So, John, what do you guys do for, like, reliability and testing?
Do you have, like, continuous integration set up, things like that?
We do all of our testing via Travis at the moment.
Well, everything except for, I would say, our performance benchmark testing.
But we actually, we test against all of the major versions of Python at the moment.
And that would be currently all the way from 2.6 to 3.6 at the moment.
Yeah, that's great. That's quite the span.
We also, we do claim support for the both versions of PyPy.
And we had a Jython job in there, but I think we were running into a few problems with the Jython.
But beyond that, we actually, we mentioned Hug earlier, and we do have, like, an integration test with them, which is very helpful.
So, I think we do run quite a few automated tests against Falcon.
And we try to make sure and maintain backwards compatibility at all costs.
Yeah, that's something I really think is highly important in the web space.
Because you see a new update come out, you pip install, upgrade, push that to the server.
If that breaks something, that's, you don't want to be caught out.
Why is the website down? Oh, my gosh, this is really upsetting.
Just a quick thought on that.
Like, one of the, this kind of came about because in some of our extremely high-scale cloud services that we build at Rackspace,
we were relying on some web frameworks that would tend to break in subtle ways, you know, just in minor version releases.
So, we felt that pain very keenly, and we wanted to be very careful about that.
So, that's kind of core to our change management philosophy around Falcon,
that we go to great lengths not to break stuff without a major version rev.
Yeah, absolutely.
John, it seems like the philosophy ties into that as well.
Like, the less code you have, the more lightweight, the more explicit, the easier it is to test and not break things.
Definitely.
And even when we do add in more substantial features, like, we have a feature coming in for 1.3 around media content type handling.
So, it'll handle serialization, deserialization, all of that.
But all of that is 100% optional.
And it's very important that it is that way and that it does not impact, you know, request times from a performance perspective.
And, like, we go to great lengths to make sure that things are architected in a way that somebody can feel comfortable just upgrading to the next minor version and not worry about breakages.
Yeah, absolutely.
I think that's great.
And unless you turn on that feature, it's not going to affect you, right?
Or in this case, it's there.
It's just you have to start using it.
Right.
But it's how the feature was designed so that, you know, it doesn't impact you unless you use it.
Yeah, that makes a lot of sense.
So, Kurt, I have a challenge for you.
It's a little bit difficult to describe code in an audio format.
So, don't go too much into detail.
But give us a sense of what it's like to program for this.
Like, if I want an API that exposes, like, customers or whatever, I can get a customer and create a customer.
Like, what does the code that I put together to do that look like?
I typically start out thinking, because I'm kind of a REST geek.
So, I start thinking about the resources.
So, I'll think about, okay, we need to define a customer, a resource that represents a customer.
And then maybe a resource that represents a list of those customers.
We'll just think about that.
So, in Falcon, you represent a resource with just a plain Python class.
Nothing super special about it, except that in that class, you have what we call responder methods.
And these are just methods that have a well-known name.
It starts with on and then underscore and then the name of the HTTP method that you want to respond to.
So, this resource responds to get requests, post requests, etc.
So, you create a method for each one of those.
Within that method, in that class, you'll receive request and response objects.
And so, this isn't too dissimilar from, like, maybe a web ob sort of a workflow where you get requests and response objects that you deal with.
It is a little bit different in that we hand you a response object.
So, you're not constructing it yourself and returning it.
You, like, fill it out.
Yeah.
So, like in Flask, you'll say, you know, you'll instantiate some kind of response and return it.
We'll pass in a pre-instantiated response, which actually saves you some work for the use cases that Falcon is designed for.
You're typically not returning different types of responses for different types of, like, say, JSON versus HTML.
Your negotiation is done a little bit differently.
But, so, you pull the information you need out of the request, do what you need to do.
You may use, like, SQLAlchemy to go talk to the backend, pull out a response, and then you fill out HTTP.
You've got the status code.
You've got the headers, things like that.
And because this is a class and you instantiate it up front, you can pass in, like, a database connection or whatever, anything like that.
There's no magic thread storage or anything like that.
Yeah, that makes testing super easy because it shows you right where to pass in the mock stuff later or other test fake things.
So, it's just straight up kind of normal Python class instantiation.
So, once you have that filled out, then you need to wire that up to a route.
So, a route is simply a mapping between a URL and your resource.
So, you'll have a place in your code.
You probably have a setup file that goes through and instantiates your resource class, passes in the database connection, whatever you need to do there.
And then you instantiate an API object, which is a whiskey app.
And then on that object, you can call, like, .add route, and you pass in the URL you want and then the resource.
And something else that's a little bit different is that from some of the other frameworks is that we don't use decorators.
We have you in stench.
You set up the routes in a central location.
Part of that is philosophical.
I mean, we talk about Python being somewhat unopinionated.
But in a few places, we are a little opinionated.
We just find that having everything in one spot makes it easier to kind of reason about your API namespace versus having it sprinkled around with decorators all over.
But that's just a little bit of a philosophical difference.
Yeah, I got to say, I kind of like that as well.
Like, you can go to one place near the app startup and go, okay, these are the routes.
This is where they go.
It makes a lot of sense.
And it just makes things a little easier.
Again, it's very clear where things are coming from, where they're going.
Because decorators can be a little bit.
I love decorators.
We use them for some things.
But sometimes they can be a little magical.
Probably the other thing to point out here is that you don't specify what verbs you're mapping to that URL.
So we are a little bit opinionated around encouraging the REST architectural style, which means you kind of think about resources.
And each resource is kind of responsible for deciding what methods it's going to respond to.
And so if you don't implement a method, Falcon will just return a method not found for you.
And it's as simple as that.
Right.
Okay.
Interesting.
So I might say in my example, slash users, users, customers, slash users, let's say.
And then that maps to a user resource class.
And there might be an on get and an on post, but no on patch.
And so would patch come back as 404 or a different status code?
It would come back as a method not found.
So you found the resource.
You had like something exists at the other end of that URI.
It just doesn't support the method that you requested.
Right.
I see.
So this is, again, this kind of goes back to the spirit of HTTP and REST and kind of a, we've read probably way too many RFCs.
And so some of that comes out through some of our design choices.
Is there a place I can make a return a teapot?
Yes, actually.
We have, just for the heck of it, I don't, you know, a couple of years back, we implemented a bunch of 700 errors just for fun.
So they're in there.
Hey, everyone.
This is Michael.
Let me tell you about Datadog.
They're sponsoring this episode.
Performance and bottlenecks don't exist just in your application code.
Modern applications are systems built upon systems.
And Datadog lets you view the system as a whole.
Let's say you have a Python web app running Flask.
It's built upon MongoDB and hosted and scaled out on a set of Ubuntu servers running Nginx and Microwisgi.
Add Datadog and you can view and monitor and even get alerts across all of these systems.
Datadog has a great getting started tutorial that takes just a few moments.
And if you complete it, they'll send you a sweet Datadog t-shirt for free.
Don't hesitate.
Visit talkpython.fm/Datadog and see what you've been missing.
That's talkpython.fm/Datadog.
John, there's a bunch of different add-ons and templates.
So like the philosophy of having it very small and very compact is cool.
But then a bunch of people have created like add-on extensions for this, right?
Yeah.
You want to highlight some of those?
Definitely.
So there's the interesting thing about the community and kind of how some of the add-ons occur is that a lot of this comes out of a desire for, in some cases, for people's needs or someone has a specific, let's say they're trying to deal with authorization or serialization.
Or they have some very opinionated way of deciding, you know, how to deal with specifications or whatever the case may be.
Falcon does allow for a lot of flexibility and control around those kinds of things.
So you can easily extend or wrap aspects of Falcon.
One of the interesting things that we did discover, you know, through the number of people who were writing effectively serialization and validation add-ons for Falcon,
we ended up taking a lot of that community feedback and, you know, compiling that into the features that, you know, the media content type handling that's going to be coming in one or three.
Right.
That's the thing you guys were just talking about.
Yeah.
That like content negotiation stuff that you were just talking about.
Yeah.
So like there's a lot of frameworks have very opinionated ways of looking at it.
Myself, like I've used quite a few different methods depending on the needs.
And, you know, for whether it be, you know, EMC, Rackspace, personal projects, whatever it may be,
you know, everyone has a little bit different ways of handling data or validating it.
And so trying to find a uniform and generic enough approach for everyone took quite a long time.
But some of that didn't occur until a lot of our community members started writing their own implementations.
So it's very cool to see kind of how that evolved from that.
You know, it started as an add-on and now it's become something that's going to be baked into the framework and the next release.
So you had like five or six examples of people trying to solve the problem.
You're like, I think we can put it all together like this, huh?
Yeah.
Most definitely.
We try to, you know, we're trying to be careful because we want to leave space for people to go and innovate and do these sort of third-party add-ons.
And we don't want to be too opinionated.
But in cases like these where we've seen a lot of, you know, it's pretty much something everybody needs.
We're moving towards a place where we think we're going to start creating some basic, just a basic way to get started out of the box.
And completely optional and still allow room for other people to build more sophisticated solutions.
But just to give somebody, people something to get started with.
Yeah, of course.
So are you thinking these are like extra packages that you can pull in?
Or are they going straight into Falcon, the package?
There are all, I believe all of these are usually directly on PyPI.
Some people have like just avoided that step and they just build them into their almost pseudo frameworks.
That's it on top.
I know for several smaller projects that I've done, I've had a very specific problem and I built middleware to solve the problem.
And they were never, it was never upstreamed or anything like that.
But it was great to solve the problem for the business need and it was carried around.
But there's no sense in upstreaming a lot of that.
So, but I think most of our contributors have just pushed up a PyPI package with that starts with like Falcon dash and then whatever, whatever they wanted it to be.
Yep.
Yeah.
That makes sense.
Falcon Forbes is a great example, a common use case, right?
For APIs, being able to access them from like single page apps and things.
And so we had someone who's contributed a few patches to Python say, hey, should I just build this out and should we make it part of the framework or not?
And he just ended up kind of maintaining it separately.
And I think that's great.
You know, I think that's kind of what open source community is all about.
For the stuff that we pull in, I think one of the deciding factors for us is what dependencies it brings with it because we don't want to like force extra stuff on the operators if we don't, that they have to kind of manage.
And also the more dependencies you bring in, the more likelihood that they might cause bugs or problems.
So we try to keep our dependency list super short.
So if it's something like JSON, like the built-in media handling helpers that John was talking about that are going to be in the next release, like, you know, they just use the standard library JSON.
Yeah.
So they don't bring much baggage with them.
And it's very basic stuff.
So it doesn't bring a lot of baggage with it.
You know, you start looking at some other things, it starts to be kind of heavy pretty quickly.
So we might, you know, we're kind of exploring our options, trying to still kind of experiment with how we want to do this.
I think over time we'll probably have a few projects under the falconry work that we maintain.
But we want to make sure we don't stomp on anybody's efforts to kind of do something really interesting out there in the community.
Sure.
Yeah.
Maybe have like some cookie cutter template type things that will bring in these additional libraries and like make it easy to get started, but not make it part of the project itself.
People don't want them.
Definitely.
We've actually talked about that a bit.
And I know I've been playing with a few things on the side.
I haven't actually pushed up anything yet.
But we've had several discussions, especially since PyCon, around how we can make that adoption and like building of projects a little bit easier on the community.
And so hopefully we'll have a better answer around that, you know, in a bit.
Yeah.
Sounds good.
So, John, let's talk about hosting.
You can run falcon, obviously, on CPython.
As far back as 2.6 and as far forward as 3.6.
So that's really great.
It also runs on PyPy, right?
It does.
Both PyPy, you know, to, I guess, PyPy 2 and PyPy 3.
From like a, how Falcon can be deployed is a very interesting, in a lot of cases, it just kind of comes down to what your needs are.
Because some people, like there are still performance differences between 2.7 and 3.5, 3.6, 3.7.
A lot of those performance differences in Python have started dwindling.
But there are still differences, especially with PyPy 3.0.
There's still some performance disadvantages.
So like if you needed top performance for whatever you're doing, maybe it's not quite there or ready for you yet.
In a lot of cases, while I generally deploy with PyPy, a lot of people that I, you know, talk with, they're more than happy with 3.5 or 3.6.
Right.
Straight CPython 3.5 or 3.6.
Yeah.
And I guess that comes back to the, like, how much of it is the framework that you're worried about versus how much of it is your internal code and the stuff you're doing internally?
How much can it leverage the speedups of PyPy versus does that thing you're using have some kind of C speedups anyway?
And so it would lose those or whatever, right?
A lot of the performance problems that we see are not necessarily in the Python directly.
I mean, there's a lot of speed advantages you can get by using PyPy.
And I highly recommend people using it.
One of the difficulties that we see, especially in recent times, is dealing with the WSGI servers themselves.
And I know this is something that really came up over in discussions at PyCon between the Django REST framework.
So that'd be Tom Christie, Falcon, and Flask.
And we were all talking about how to deal with some of the bottlenecks we see in the WSGI servers.
Like, I personally do play with G Unicorn, and I think it's great.
But there are certain bottlenecks in the WSGI servers currently.
And, yeah.
It does, like, you can sometimes squeeze out more performance out of using, like, UWSGI or MicroWSGI.
But, yeah.
We run into quite a few problems right now on that.
Well, and then there's the whole async side of the story that doesn't even fit with WSGI or the HTTP2 thing.
And there's a lot of room for those to get better.
Most definitely.
And that's actually what Tom Christie from Django REST framework and API Star, like, that's a lot of the work that, you know, he's exploring right now.
And Uveacorn is to try to deal with this kind of compatibility between async and G Unicorn and trying to resolve some of these WSGI-ish philosophies.
So it's very fascinating.
I imagine that the story around this will radically change in the next year, which makes me very excited.
Yeah, me too.
I think it's definitely a place where there's a lot of flowers blooming.
And somebody's going to crack this problem, and we'll just agree on it.
And it'll be like WSGI.
Of course you use that.
What I really like about Tom's approach is kind of up to this point, a lot of the attempts to crack this have been monolithic.
Like, someone will have a web framework, but then they'll build in, you know, an async web server.
And it's kind of hard to just use their web server, and it's fairly opinionated.
But building an async worker type for G Unicorn, exploring sort of a way of creating a de facto interface for that.
Nobody's really interested in doing like a WSGI 2.0.
But, you know, we need something to kind of code against so people stop implementing it every 10 different ways.
That's right.
So, yeah, we're following his work closely.
I'm hoping to contribute once we get a little bit more time here.
And we'll kind of see how it goes.
Yeah, that'd be great.
It'd be really cool to see something come out of that.
So, another thing around this performance and ways to host and run and work with Falcon is you guys also do something interesting with Cython, right, Kurt?
Interesting thing with Cython.
Cython, if you're not kind of familiar with it, it translates your Python code to CPython code and then compiles it for you just kind of automagically.
And if you want, you can add additional annotations to your Python code that will basically give hints to Cython.
So, you can say, hey, this is an int or treat this as an actual array and it's going to be a fixed size or things like that.
And then that allows Cython to do even more optimizations on it.
But you can simply compile any Python code.
You can run it through Cython.
It'll compile it for you and you get just the measurements I've seen in around 10, 20% decrease in your CPU cycles just by doing that.
That's cool.
And that's not compiling your code running on Falcon, but compiling Falcon itself once you've installed it, right?
That's right.
So, in the setup.py file, it just detects Cython if you've installed it.
So, it's an optional dependency.
If it's there, then it'll just use the build extension from Cython to pull in all the Falcons.
You could certainly do the exact same thing with your own code.
It's not terribly difficult.
It's kind of a nice, easy way to get a little bit of an extra performance boost if you are sort of invested in CPython.
If you can move to PyPy, then you'll see a much greater increase.
But not everybody can do that.
Right.
That probably depends somewhat on, yeah, it depends on the libraries that runs inside your methods.
Yeah.
Cool.
So, while we're on the topic, let's talk about performance.
You guys have some benchmark numbers that you put up there.
And I just, I can feel the challenges every time I see benchmark numbers.
Well, people shooting arrows at it.
No, you didn't do it this way, but I did it that way.
If I do it this way, it's faster.
Yeah.
It's just, but I still feel like they're kind of important to give you a general sense.
Right?
Mm-hmm.
So, on like CPython, you have, let's see, you've got Flask coming in around 4,200 for this particular benchmark.
You lay out the details on the website.
Like 4,200 requests a second.
You've got Bottle going at 16,000, but Bottle's like a super micro framework.
And then Falcon coming in at 30,000, which is really nice.
So, sort of use Pecan as a baseline, and it's 28 times faster than that.
So, that's cool.
Pecan was one of the frameworks that we were looking at for developing some services earlier on.
So, it just happened to end up in the benchmarks.
And we probably need to add Django.
It's a fairly straightforward benchmark just to show you what's possible, really.
Right.
How much of a difference it can make to kind of remove some of the layers and the abstractions.
And you may end up not needing, you know, some people are, a lot of people are kind of moving to Go or looking at some other, or Node, looking at some other options.
But you may not need to.
Maybe you just need to use something a little bit lighter.
But we try to be very, very straightforward about what this is and how we've done it.
But you certainly need to go benchmark your own use cases.
I mean, for that messaging service that we use for cloud backup I mentioned earlier, I went and built out an almost full implementation in Node and in Python and benchmark both of them to see which would do better for us.
So, yeah, you've got to do your own homework.
But this gives you a rough feeling for what's possible.
Yeah, that's very cool.
I was going to say, in addition to that, one of the things that is often kind of missed as a part of the benchmarks that we do is that we do remove the WSGI server from the benchmark.
A lot of for the reasons why I was mentioning earlier around the performance constraints that occur in the WSGI server.
So that's where we really encourage people to focus on what their use case will actually be, because that's really the numbers that will, at the end of the day, matter.
So you can do great things, and they can be extremely fast.
It just really depends on your configuration and your use case, because the benchmarks that we ended up doing were primarily to illustrate overhead within the framework themselves.
And, you know, to show that kind of, this is where we sit from a, how much load the framework has on the entire process.
So the theoretical maximum currently.
Right, yeah.
If you did nothing, you could maybe get this.
Yeah, and it's also worth pointing out the PyPy one, where, as I said, the CPython one was at 30,000 requests a second.
The PyPy one is 345,346.
So that's a really dramatic increase.
One of the things I know, I've definitely used PyPy quite a bit in more larger scale caching services.
And the higher performance nature of running Falcon under PyPy has really saved, you know, saved the situation, so to speak.
Yeah, that's really cool.
Another piece of advice you guys have is to use, is it micro JSON, UJSON?
If you're using CPython, because it'll speed up the serialization and query string parsing and stuff.
But skip it on PyPy, because otherwise it'll have to fall back to c types, because micro JSON, I'm guessing, is partially implemented in c.
PyPy has been historically at a bit of a disadvantage when it comes to c types.
And they've been getting a lot better at that, so we'll see where that goes.
But if you're using Python CFFI, it works a little bit better, better optimized for that case.
This just kind of goes back to the tradeoffs, right?
I mean, there are a lot of nice kind of drop-in replacement libraries you can use that are highly optimized.
But make sure you go and look at actually how they're implemented.
They may be faster on CPython, but slower on PyPy.
Yep. Measure, don't guess, huh?
Yep.
John, how about some notable users or deployments?
Yeah.
So there are, we've got quite a few people from various organizations.
You know, people from, you know, LinkedIn, they have a few open source projects that use us.
EMZ, obviously, since I was there.
OpenStack.
Wargaming, which for people who are in the gaming world, I believe they do use us for certain aspects of World of Tanks.
Oh, that's cool.
Rackspace, obviously.
In fact, I think there's a talk that was done by some of the warm gaming people in Russia over some of their usage.
Yeah, we've got a lot of people.
I think last time we checked, we get it for stats are a good thing.
And I think we get around 50,000 something downloads per month with PyPy.
That's awesome.
A lot of people using it in various circumstances.
I guess you...
A lot of people using it for internal things.
Yeah, they're not going to talk about it probably.
Yeah.
There's also everyone using Hug in a sense, right?
I guess.
That's actually one of the kind of very interesting things about Falcon and his current position of having someone like Timothy coming along and building a framework on top of us.
We don't necessarily get the advantages from a download perspective.
But we get users by proxy almost, which is very interesting.
Yeah, and probably improvements made at your level by way of that framework also help you.
Definitely trying to understand some of the use cases that occur in a framework like Hug definitely help kind of inform some of our decisions.
It helps us...
It almost helps keep us honest going back to the whole continuous integration.
It's great to have almost like a classic use case that we can test against.
Yeah, that's really cool.
All right, gentlemen.
I think that is all the time we have to talk about Falcon.
But let me ask you the two questions I always ask at the end.
And Kurt, I guess I'll start with you.
Favorite editor, if you want to write some Python code, what do you open up?
So I live and breathe in Sublime.
It's kind of my working horse editor.
So I used to, years ago, I used to be more of an IDE guy.
But I've kind of taken the pragmatic programmer's advice to heart and tried to find something I can use that's a little more versatile.
I can kind of use for everything.
And then I don't have to context switch with my brain.
Yeah, makes sense.
So it's a nice mixture between having access to a lot of keyboard shortcuts and whatnot.
But I can also kind of use my mouse for certain things that are more efficient that way.
Sure.
John?
NeoVim.
I am one of those Vim people.
All right.
Awesome.
And notable PyPI package.
What do you guys want to recommend?
Kurt, go with you first.
Oh, sorry.
Go ahead, John.
One of the ones I like to recommend is the testing.libraries.
A lot of people, they talk about having to mock up database interactions or, you know, when they're trying to test their API.
Whenever there's a Python package that will actually, on demand, set up a local instance of like Postgres or Redis or MySQL.
And then tear it down as a part of your tests.
And you can eliminate a lot of testing burden just through those packages.
So I'm a big fan of them.
Yeah, that's really cool because sometimes mocking out the data layer is just like so much work for that tradeoff, you know?
It is.
And you also need to test your migration.
So it's great for that.
Yeah, cool.
We mentioned UVicorn a few times.
That's Tom Christie's kind of new baby.
And he's doing some impressive work over there.
So I invite everyone to check that out.
He uses the MagicStack HTTP parser and AsyncIO drop-in.
Some pretty impressive performance numbers out of that.
Some interesting work.
So check that out.
Yeah, it's cool.
It's based on UVloop as well, right?
Yes.
Yep.
And probably just another one.
I want to give a shout out to Brian Warner's Magic Wormhole project.
I think he gave a talk at it a couple years back at PyCon.
But it's just a really clever, easy way to securely ship files from point A to point B to send something to a friend.
It's like on-demand Dropbox from the command line with a one-time code thing.
Yeah.
I mean, whether or not you even care about the security, it's just a really slick way to ship files.
So check that out.
All right.
Yeah.
Good recommendations, you guys.
Very nice projects.
All right.
Final call to action.
People want to get started.
What do they do?
Go check out falconframework.org.
It just gives you a quick overview of the project, has links to GitHub, has links to our Gitter channel.
We have a couple channels there.
There's a user channel for just getting started, asking questions.
We have a dev channel for contributors.
And, you know, check that out.
Once you get playing with the framework, if you run into any issues, reach out to us.
We're always happy to help.
And we're always looking for contributors, certainly.
So of all levels, we're happy to help you get started there as well.
All right.
That's great.
Yeah, definitely a cool project to get involved with.
A lot of people ask about what open source project they might get a chance to, you know,
they want to do their first open source thing.
This would be a fun one.
If you're interested in kind of learning the fundamentals of the HTTP protocol,
which is a surprisingly complex protocol, you know, it's a good way to kind of get under the hood
and see how it all works.
Yep.
Sounds great.
Thank you guys for being on the show.
This project is really, really interesting.
I'm glad to see it being successful.
Awesome.
Thank you.
Thanks a lot.
This has been another episode of Talk Python to Me.
Our guests have been Kurt Griffiths and John Verbonic.
And this episode has been brought to you by Linode and Datadog.
Linode is bulletproof hosting for whatever you're building with Python.
Get your four months free at talkpython.fm/Linode.
Just use the code Python17.
Datadog gives you visibility into the whole system running your code.
Visit talkpython.fm/Datadog and see what you've been missing.
Don't even throw in a free t-shirt for doing the tutorial.
Are you or a colleague trying to learn Python?
Have you tried books and videos that just left you bored by covering topics point by point?
Well, check out my online course, Python Jumpstart by building 10 apps at talkpython.fm/course to experience a more engaging way to learn Python.
And if you're looking for something a little more advanced, try my Write Pythonic code course at talkpython.fm/Pythonic.
Be sure to subscribe to the show.
Open your favorite podcatcher and search for Python.
We should be right at the top.
You can also find the iTunes feed at /itunes, Google Play feed at /play, and direct RSS feed at /rss on talkpython.fm.
This is your host, Michael Kennedy.
Thanks so much for listening.
I really appreciate it.
Now get out there and write some Python code.
I really appreciate it.