I recently discovered MongDB Realm and it's gotten me quite excited. So in this post I'll tell you all about it, and why I'm finally (partly) on the "serverless" bandwagon.
Have you ever felt that your restful backend was simply a permission layer between the database and frontend? This is often the case for simple, single-user web apps (such as Pensify!). Under this paradigm, you define a number of endpoints which each perform some transaction on the database. Most of these endpoints will: 1) check the user is authenticated, then 2) ensure that this user has permission to view/modify/delete the respective database object.
This leads to a tonne of code duplication and an overall annoying developer experience.
So how can we solve these two problems..? Well:
With Realm, you specify the data access rules at the DB-level. Then at runtime, Realm will dynamically determine read & write permissions for every object included in the request (don't forget to include your JWT as an auth header in all requests!).
For example, you can specify in the table schema that a user can read all records, but can only write records if the
userId field in the POST data matches the current user itself. And with just that, we can create a pretty decent blog / comments platform without a backend.
This, in my opinion, is game-changing. For this reason alone, I have decided to pivot to serverless for Pensify, and get rid of the Express backend altogether.
But wait ... there's more!
Have you ever built a web app which needed continuous internet connectivity, but only because it relied on synchronous data-syncing between the client app and the database? Again, consider a simple single-user client-side app like Pensify. Once the user has loaded the application bundle and the initial state (from the DB), it can really operate offline indefinitely. The only problem is that the application state would deviate from the database state.
The conventional way to solve this is to add a request adapter which remembers all failed requests, and waits for network reconnection before re-submitting them. If you want to learn more, see axios-offline or this blog post.
This approach works fine, but it's complicated and error-prone and bad at resolving conflicts where multiple requests edit the same database object. The problem is that we're trying to engineer a complex solution in order to preserve the online-first paradigm. The precursory assumption was that all database transactions need to be conducted on the central/cloud database, and thus we must have some sort of FIFO query queue.
Enter: Realm Sync. With Realm Sync your application maintains a local (offline) database on the mobile device itself. Transactions are performed first on this local database. Then, if and when, network connection is available, this local database is synchronised with the cloud database.
The obvious and massive benefit is that you do not need to write your own synchronisation protocol. Realm also resolves conflicts at the DB level, using strong eventual consistency. This confusing term simply means that two database nodes (e.g. the mobile device and the cloud database) will arrive at the same state regardless of the order in which they received the series of transactions.
Finally the downside, Realm Sync is not available in the web app context, only on mobile. Bummer. Nevertheless, Pensify will one day have a React Native counterpart, so Realm Sync is still relevant. At a minimum it cements MongoDB's place in my tech stack for simple noSQL apps. Well played Mongo...