Building a large-scale osu! private server from scratch

October 3, 2016

Hello there! It’s been a while. In the past few months, I’ve been working in most of my spare time on Ripple, which is an osu! private server I built with a friend of mine, Nyo. Ripple is my first large-scale project I’ve built, and so I’d like to share my experience in my past year and something writing code for it.

A bit of a summary, for those of you not coming here from Ripple:

Ripple was born out of my mind the 12th of August, 2016. Few days later, my pal Nyo came in, and started contributing a hell lot of code, and in about a week or so, we were set up: we had a domain, we had the server working (it was score-only, it did not have bancho), and we were playing on it with about 10 friends of ours. But, shortly, after a month, I decided to shut down the project, because peppy was going to add HTTPS to osu!, and I believed it would have been impossible to get it working (turns out it isn’t). Fast forward from September to January, Nyo decides that it’s time to bring Ripple back to life, especially since justm3, a famous member of a certain osu! hacking community, released the source code of his bancho server.

The reason why we didn’t have a Bancho server when we started out with Ripple was that we were clueless on how it worked, and I, who was in charge of understanding the protocol, understood jack shit about it, especially since I knew little about binary encoding. Anyway, taking justm3’s code as reference, Nyo wrote a bancho server. It was ugly, it used PHP and MySQL (not even redis!), but it worked for the moment. We still refrained from advertising ourselves to the public, but we started allowing people to come in slowly, so we had more users than what we did initially.

Now, at this moment in history, Ripple’s very terribly performing. It’s all PHP, and as you may know PHP pretty sucks when it comes to performance, especially for real-time chatting and streaming systems. So the Great Rewrite started (I’m kidding, we didn’t actually name it like that).

So, how did we optimise Ripple?

Rewrite Bancho

The very first thing Nyo did soon after getting the PHP bancho (nicknamed potatobancho) done, was rewriting it in Python. And well, guess what, it worked waaay better. A lot of the code is still in use, although as usual a lot of it like in most programs has ben rewritten.

Rewrite the cron

So, here’s the thing. We had a PHP script up until a few months ago, that used to do some administration tasks such as recalculating Leaderboards, ranked scores, accuracies, and all that stuff. Here’s the source. It was first made in the first version of Ripple, and no surprise here, it sucked. Keep in mind that that was waaaay back, like when we had 300 or so users (today we have over 10,000). Since we wanted it to actually be fast and scalable, I took care of it and rewrote it in Go in about a week or so. This was the outcome (see especially the last part of it, where the workers are maximised). So it went from being a slow-ass script, to being a modular program that is super-fast and can do what was done in 3 minutes in 10 seconds or so. Even today, the cron still takes about 30 seconds to execute, and I’d say that’s pretty good scaling.

Rewrite the score server

This was another very important thing to do. As we grew, it became more important to have the responses to osu!’s unofficial API (the one the client/game itself uses) be done extremely fast, so that people can have a flawless experience playing the game. Again, this was done with Python. LETS is probably one of our most important projects, as it’s really the core of a lot of stuff, like leaderboards, score submission and downloading replays. While it’s still not fast as we’d wish it was, mainly for technical issues which would take a lot of time to fix, it’s still pretty fast and does a good fucking job at replacing the old PHP shitty scripts.


Something a lot of people forget to do when writing query is adding LIMITs whenever they can. As it turned out for us, along with adding a hell lot of indexes to our tables, LIMIT 1 made our second best imprvement in performance.

Getting rid of the current website.

If you do not have horrible taste in design, you’ll have noticed that Ripple’s design is absolutely disgusting as of right now. That’s the main reason why I am currently building a solution to that, which is codenamed “Hanayo”, from the Love Live! character. Also, there’s the performance reason to why I’m building it: the PHP version was very resource-straining and especially very slow. Usually pages took about 500ms to one second to generate, and when it comes to the admin control panel, it goes even higher than that, up to 2 seconds.

Currently Hanayo is really fast, and requests are usually ~100ms, still a huge improvement. I can say that developing Ripple in the past year has helped me a lot developing my skills as a programmer, mostly when it comes to building large-scale products, since Ripple actually is my first project that I can say really succeded. It is also the first project I start and make completely with a friend, which in my opinion means a lot, since it tells how much working together with someone else is important when making a project. For the two of us, the thing that drives us the most for what matters the development was the fact that whenever either of us doesn’t feel like developing for Ripple, seeing the counterpart doing work makes the non-working part want to go back to write some code. Now, I could probably write the previous sentence better, but I don’t want to go research way of saying it so that it doesn’t sound so completely fucked up. You get the point, anyway.

© Morgan Bazalgette 2015-2017. Back to main site.