Navigation
loading...
loading...
20 Apr, 2015

Building better Node.JS apps with RethinkDB

posted in Development

whyrethink

We’ve been using RethinkDB in production for almost a year. RethinkDB is an open-source database designed to make it dramatically easier to build and scale real-time apps. Last week, the 2.0 release of RethinkDB landed and it was given a shiny “Production Ready” badge. After five years of development, RethinkDB is ready for general adoption!

When we often speak to other Javascript developers using Node.js or even io.js, the common consensus is to use either MongoDB or herald back to the safety of a SQL database. It’s awesome when you find a database you’re comfortable with – please continue using whatever best suites your needs, however it’s a shame that developers often prefer to bring out the elitist perspective when it comes to technology used; at the end of the day, the language or technology you use either empowers you or slows you down. This blog post is about a technology that’s empowered our development team from some of our earlier prototypes to the production application that serves over 70 million API requests a week.

Why RethinkDB?

We spent nearly 2 weeks researching database technologies and considered CouchDB, PostgreSQL, FireBase, MongoDB, and even falling back to MySQL. Here are some of the important decisions that helped us pick RethinkDB almost a year ago.

Data structures

The biggest initial problem we encountered when we started designing NodePanel were the limitations a schema-based database engine presented. Minecraft servers alone have thousands of mods, plugins, and game variants which can change at any time. A schema simply wouldn’t work well for us – we needed NoSQL.

Performance and scaling

Today we are building one of the first real-time game server hosting control panels. Being able to scale our database between multiple servers by sharding and replicating data was a must. We’ve managed to set this up with MySQL in the past, but it was a massive pain in the rear. RethinkDB’s ability to handle sharding and replication flawlessly behind the scenes is one of the reasons we started considering RethinkDB. The fact that these features were considered from the ground up made RethinkDB the victor in this round, nearly unchallenged.

Self-hosted

We came really close to using a third-party service such as Firebase due to the ease of deployment, but eventually settled on self-hosting using rented hardware. The real problem with using a service such as this is that you are relying on another company to hold some of the most precious information a technology company can have. Not to mention the fact that your local development builds have an added layer of complexity, as you can not run all the services you need locally.

Query Protocol

This strongest argument from our team for RethinkDB, was the way that data is queried. Long gone are the days of writing an application with 3-5 languages that you need to switch between. For example, if you develop in PHP & MySQL you end up using PHP, MySQL, & Javascript eventually as three different languages that you must switch between, while building the application. We feel that this is one of the most driving arguments that server-side Javascript has had for developers.

Forcing yourself to remember to sanitize your PHP so that it can properly be read by MySQL simply isn’t comfortable, but more importantly leads to bugs or vulnerabilities in your code. ORMs or wrappers for a library may work, but in our experience it makes complex or clever code difficult to execute – we needed something that spoke Javascript.

Talking to RethinkDB with Javascript

It’s taken us this long, but we can finally talk about doing some programming! Lets create some code, which works with an example user dataset:

Get a single user, by ID

r.table('users').get(123).run(function(err, user){
     // ... an object that contains our user
});

Update a user, by just adding to our selection query

r.table('users').get(123).update({
     'status': 'online'
}).run(function(err, user){
     // ... an object that reports the number of changes made in the database
});

Get all Users

r.table('users').run(function(err, results){
     // ... a cursor to stream through the data which can also be converted
     // to an array using the toArray method
});

That’s neat, I guess, but that’s not real programming. That’s the kind of programming that you’ll see on marketing – it doesn’t deal with variable data and it doesn’t do much that couldn’t be done with a basic JSON file.

Let’s search for users, using their signup dates. We want to know our users that have registered in the past 30 days, so we can ask them how they’re finding our service!

var signupFilter = new Date();
signupFilter.setDate(signupFilter.getDate()-30); // get a timestamp from 30 days ago
r.table('users').filter(function(user){
     return user('signup_date').gt(signupFilter);
}).run(function(err, user){
     // ... a cursor to stream through the data which can also be converted
     //  to an array using the toArray method
});

Wait, did we just perform a a callback function inside our database query? Yes, but we also used a native Date object from Javascript to make a time comparison. This again means we can write Javascript, even when talking to our database!

Oh wait, did we mention it has a real-time event engine?

Displaying data in real-time has become paramount for our team, especially when dealing with monitoring game servers. Rather than having to respond to code as we update our database, we can now create monitors to check for problems as the database finds them – it makes sense that your database is event driven, just like your application is. RethinkDB powers many of our real-time logging solutions with admin alerts when necessary.

This is just the surface…

The reality is that the amount of time and effort the team at RethinkDB have spent on their product has superseded what we would ever expect our database to do for us. It has support for Lat/Long data with geospatial queries, can consume an api to populate a table, an excellent streaming api, table joins, and much more. We look forward to the future of RethinkDB!