Ten years ago today, on the blog for Project Dirigible, we announced that we’d recently launched a new site called PythonAnywhere. It almost didn’t happen! The project we were working on was something completely different, and it was only when we looked at how it was being used that we realised that it held the seed of a much better idea.
Project Dirigible was an online spreadsheet,
based on Python. Unlike a traditional spreadsheet, where cells can hold only numbers, dates and text,
it supported any Python type, so a cell could contain a list, an object, a numpy array, or even a function
(so, if you don’t value your sanity very highly, you could write a formula like this:
=A1(A2.value, A3, A4(A5))).
We’d been hoping that Dirigible would be the breakout success that Resolver One, our desktop Pythonic spreadsheet, had never been, and would help us free the world from the tyranny of Excel. It was getting some interest, with a reasonable number of people signing up and using it, but we’d discovered something odd:
When we asked Dirigible’s beta testers what they were using it for, a surprising number said that it was for general Python development online. They weren’t using the spreadsheet grid at all!
In retrospect, perhaps it shouldn’t have been so surprising. People want to write Python code, and sometimes they don’t have a computer with it installed to hand – and it’s always useful to have your code accessible so that you can work from anywhere. Programmers have flexibility in the tools they use and can relatively easily move to a new system. By contrast, spreadsheet users have a lot of existing documents that they want to keep, and many of them are far from being technical people. They really don’t want to move to something new.
So, we started PythonAnywhere. Here’s a potted history of what happened next.
While our first blog post was on 5 August 2011, PythonAnywhere development had started a little earlier; delving into our git history, I found this:
- 2011-04-01 13:21 6f7530588 Initial commit - used Dirigible as a base. First pass at stripping out Dirigible-specific stuff. by: Glenn, Harry
From our email archives, it looks like we had a very limited beta starting in late April, and after four months of coding, we had something that had enough there (and enough bugs fixed) that we were ready to go officially live. It was quite different to what we have now – the consoles were there, as was an editor, and you had a filesystem to store your data. But there was no way to build a website, no scheduled or always-on tasks, no databases. It was essentially IDLE, but online. 1
It’s been a busy ride ever since then. PythonAnywhere took off fast, and we moved all of our development efforts
over to it; first Resolver One and then Dirigible fell by the wayside. People flooded us with excellent ideas
about what to add, and scheduled tasks arrived on 18 August 2011,
websites on a subdomain of
pythonanywhere.com were released on 11 October, MySQL on 16 November,
and our forums on 13 December. Obviously, we couldn’t keep the lights on and the servers running without
some money coming in, so we released “Premium” accounts on 13 March 2012. Custom domain support appeared on
Naturally, as time went by, that breakneck speed of development had to slow; as our platform became more popular, we hit scaling issues and had to address them. And some of the technology choices we’d made initially had to be changed. Scaling is hard; for comparison purposes, the first release of PythonAnywhere ran on a single server (if memory serves, an AWS m1.xlarge) with a few hundred GiB of storage space for user accounts, and an attached MySQL 5.1 server with 40GiB storage. As of today, the main US PythonAnywhere site runs across more than 100 AWS instances, with a further 25 or so supporting our EU systems. As you can probably imagine, there have been quite a few infrastructural changes along the way!
But still, we were able to keep on: Postgres was added on 1 October 20142, our education features
started being built out on
3 February 2015, Jupyter/IPython notebooks arrived on 23 December 2015, different system images (without which we’d
still only support Django 1.3.7) on 14 September 2016, a site redesign on 30 November 2017 (we’re probably
overdue for another!), always-on tasks on 24 October 2018, one-click
HTTPS support on 19 December 2018, and our EU-hosted site at
eu.pythonanywhere.com on 7 February 2019.
Over time, we did find that we had to limit some things for free accounts, both to prevent abuse by people using our site to hack into others and just to stop us from accumulating defunct accounts. We’re very proud to be able to offer functional free accounts rather than some kind of limited thing to get people using our site just to tempt them into getting paid ones, so it’s great that we’ve never needed to lock things down further.
On 13 March 2020, like so many people around the world at that time, we started working remotely, and we blogged about it on the 20th. Initially it slowed down our development, but we adjusted quickly, and in May and September we pushed new system updates, and then again in February and March this year, and once more back in June. It looks like we’ve recently been a little remiss in blogging about the important changes, though. If you’re active in our forums, you may have noticed lots of discussion about a new virtualization system – that’s something that was critical for almost all future developments, and is now live after a lengthy beta process. We’ll have to post about it in detail soon.
So, what next for PythonAnywhere? According to GitLab, we have 1,386 open tickets, ranging from the simple (“please include package X in your pre-installed modules”), to the obscure (“Shared files can’t render if multibyte character crosses a chunk boundary”), to the apparently-easy but actually hard (“dark mode for the UI”), to the really tricky but clearly super-important (“support async web frameworks”). We tend not to announce what we’re working on ahead of time, just because things can change so quickly – we’ve found that promises lead to disappointment, disappointment leads to anger and anger leads to pain. But we do weight every ticket by the number of people who’ve asked for it – so you can be sure that if something is a popular request, we’re on the case, even if it requires significant backend changes that will take time.
Onwards and upwards! From a London-based team working on a side project for a spreadsheet company that was still working towards product/market fit, to a global all-remote team running a profitable and growing platform-as-a-service, things have changed a lot for us over the last ten years. And we hope that over the next ten we’ll be able to keep building out an ever-better site making things easier for Python developers around the world. To all those who’ve helped us over the years, by using our site, making suggestions, and generally being there for us, our most heartfelt thanks :-)
We did have one feature in that first release that we later had to switch off – you could sync your files to PythonAnywhere using Dropbox, just by sharing a folder with us. That was really nice, but sadly it didn’t scale. As soon as we got over 1,000 shares or so, Dropbox had serious problems accepting new ones. That’s completely understandable – no normal user of their service will have that many shares – but it meant that we couldn’t stick with that model. So, we stopped supporting it, and decided to focus on other, more popular features. ↩︎
The author remembers that one particularly well – we’d been working on it all-out for months, and it was ticket #3201 in our task-tracker. We had finally finished it, with many late nights, and I went for a much-needed beach holiday. I arrived at the hotel, and checked in – to my horror, the room number was 3201. ↩︎