I'm really excited to provide this look inside how we host our web apps, API, and more at Talk Python. In this first chapter, I will focus on what we've tried over the years: What worked, what was better, and why/when we changed our hosting setup. We'll set the stage and see how our deployments have evolved over time. I think you will find it refreshingly simple.
On the other hand, if you're interested in cloud-first, cloud-native apps with deep integration into cloud hyperscaler's services, you'll need to look elsewhere.
Talk Python is 9 years old at the time of this writing. It's a Python web app that is significantly more complex today than when I created it in 2016. Yet it still shares much of the original architecture and decisions from way back when.
Have you heard the phrase "You're not Google, you're not Facebook, and you're Netflix"? The TL;DR; is those tech giants that have 1M+ concurrent users. They have a hard requirement for no downtime. It's not "let's limit downtime to 5 seconds a month", no. It's zero seconds, period. They have hundreds of engineers and billions of dollars to throw at these constraints.
So when you hear unique advice from folks in that space about scaling Kubernetes clusters and globally synced DBs, admire it and then choose the simple path.
It's with that in mind that I'll share some details about our users and traffic so that you can decide whether this is close enough to your use case to take my advice as a roadmap or see it as another interesting view into a different world than yours.
When I talk about our tech and infrastructure in this book, it's all the Talk Python apps, not just the podcast or the course website.
Some stats:
* Most sites would have more static requests than Python ones (think about every image, CSS file, etc. per page). But in Talk Python-world, we do an insane amount of RSS requests per month which flips the balance.
Let's talk about the journey. When I first launched Talk Python, it was just the podcast website and a manageable amount of mp3 traffic. I was very good at web development but quite inexperienced at hosting Python-based websites. This was doubly true for anything Linux. I needed help.
So Talk Python launched on a PaaS (Platform as a Service) host dedicated to pure Python apps: PythonAnywhere. You probably didn't see that coming, did you? But their pitch is appealing, especially to 2016-Michael.
From PythonAnywhere's website: "Our basic plan gives you access to machines with a full Python environment already installed. You can develop and host your website or any other code directly from your browser without having to install software or manage your own server. All for $5/month."
Starting with PythonAnywhere gave me a chance to quickly test this flyer of an idea, the Talk Python podcast. Who knew if anyone would even show up and listen at all?
Incredibly, today, Talk Python is one of the top 3 developer podcasts in the world (across all programming disciplines).
BTW, there is a discussion to be had on whether I should have created a website at all. There are podcast hosting companies such as Podbean and others where I could have paid $10/mo, and they would handle everything. I'll cover this choice in Chapter 14: Sometimes You Should Build It Yourself, later in the book. The short version of that decision is that it's worked out to be a solid idea and has helped the show and related offerings like our courses grow over the years.
PythonAnywhere was great. But we quickly outgrew it. It could handle the traffic fine even as we grew in the early days, and the DevOps experience was quite good. But when I started getting notices of 4-hour down time for maintenance and upgrades, I realized it just wasn't a home for web apps with any sort of user base. It was for hobbyists, and that's fine, but it was time to move on.
Since I stopped using PythonAnywhere, Anaconda Inc. has acquired them, and their focus and story may have changed significantly. I have no idea. If you'd like to dive deeper into that whole history, I did a podcast episode entitled "Bringing Python to the Masses with Hosting and DevOps at PythonAnywhere" back in 2016, where I talked with Harry Percival about the inside story at PythonAnywhere.
It was time to learn Linux and get a real server. Some of you may be thinking, well, of course! But for me, this was a scary step.
For the nearly 15 years of software development that preceded my getting into Python, I had been doing development almost exclusively on Windows. I had mainly stuck to GUIs, and this even included the GUI side of IIS for hosting .NET apps. Managing servers entirely from the terminal was new to me.
I didn't want to go back to PaaS. Though, if I had to, Heroku probably would have been the right choice.
I decided on a Linux VM in the cloud. Time to search for a new host. I had previously used AWS extensively. They were super expensive and increasingly complex. AWS was out. That goes double for Azure.
I found DigitalOcean, and I was in love. They were simple, affordable, high-performance, and highly available. I created a $10 Linux VM and started figuring out how to admin a Linux VM. Here's a $200 credit for DO if you plan to create an account anyway.
[SIDEBAR "It's the complexity more than the cost that troubles me. I've shared a bunch of numbers about pricing and will continue to do so. This may give you the sense that I was constantly searching for cheap options. Of course, it's important to keep the money in mind, and sharing our costs over time will be insightful. But throughout my journey, I've primarily been chasing simplicity. On the DevOps side of things, it's just me at Talk Python. I have an editor for the podcasts, videos, and external authors for the courses. But being a one-man developer and DevOps strongly influences what is right for us. Complexity is to be avoided whenever possible."]
So, I put in the effort to learn enough about Linux to admin my server. I used the excellent documentation over at DigitalOcean. I got uWSGI powering my Pyramid + MongoDB-based web app and had NGINX fronting the whole thing, serving the static content and providing the SSL.
This was all running directly on the VMs. At this time, containers existed but were less common, and I knew nothing about them. I had just learned Linux. Getting up and running with containers was a stretch for me.
Plus, this is the cloud. What is the cloud built on? Cheap, small commodity hardware! You can get a single server for just $5. Not on AWS because they are criminally expensive, but on respectable hosts such as DigitalOcean, Linode, Hertzner, and others.
As we grew, I took this idea of many cheap servers to heart. First, it was just talkpython.fm and its MongoDB instance on a single server. Then came the courses. And we needed a way to serve all those video files for the courses. Next, Brian and I started Python Bytes. And when we launched our awesome mobile apps, they needed a set of APIs, right? And on and on and on.
To get proper isolation across all of these apps, I created a bunch of small servers at DigitalOcean. At one point, we had eight small Linux servers, all running in a private network out of New York. They varied from $5 VMs to $20 VMs.
This worked perfectly. But it was a hassle. Let me elaborate.
My original thinking was that if there was some sort of server update or issue, it would be isolated to a single service. For example, if I needed to reboot the server powering Python Bytes, I could do so without messing up the courses website or Talk Python. If I hosed the NGINX config and took the service down, it only affect that one.
I was wrong.
In practice, the only reason to reboot the server was to install monthly security patches. If one server needed updates, then they all did. After all, every server was the same version of Linux (Ubuntu 20, 22, 24, over time).
Even worse, the server hosting MongoDB also needed to be rebooted for the same reason. This database powered all of the websites combined. Rebooting it was tricky. I had to set up an elaborate notification system to reboot the servers in order and put the websites into maintenance mode until MongoDB came back online 10-20 seconds later. It worked fine, but my assumption of different servers equaling isolation and managing them separately never panned out.
Instead, I just got more complexity. And this complexity was located in the worst possible place for me. It was DevOps and infrastructure complexity rather than code complexity (which I'm experienced at managing).
After attempts to manage this with automation, GitHub webhooks, and a host of other things, it was time to move on again.