Which Database Should You Use for Your Next.js App?

PostgreSQL, Fauna, MongoDB, WunderBase. There are a lot of options out there. How to choose the right database based on performance, price, scalability, and developer experience.

•

which database should you use?

If you are building a full stack app in 2022, going with the popular choice — Next.js — will get you ~95% of the way to where you want to be, with pretty good developer experience to boot. Next.js does hybrid static and server-side rendering with good-to-great results, and you can always add third-party libraries for UI, auth, and anything else you might need.

But you're not done yet.

Even a simple ToDo app will need a database to persist information, and picking the right database for your project will depend on a number of variables. Simply going with the most popular choice might actually tank your app's performance and growth.

So which database should you choose?

To the best of my ability, I'll break down some options by what they are, how to get started, and — most importantly — what it's actually like to work with them as a boots-on-the-ground dev.

1. PostgreSQL

What is PostgreSQL?

Ah, yes. The vanilla ice cream of the web dev world.

A free and open-source, enterprise-grade, relational database that's been around since 1996, and is widely considered the most reliable, performant RDBMS in the world, supporting both JSON (non-relational) and SQL (relational) data.

How do I get started?

If you own a server already, you can probably run Postgres there too — pretty much every host offers a PostgreSQL provision from the very first tier onwards.

What's DevEx like?

I could always run Postgres well on boxes of pretty much any spec, and it's simple to set up, too. Is it operationally complex, with performance footguns? You bet. But footguns aren't bugs, and if things do go south, chances are you'll find something online to help you get back on track. The Postgres open-source community is experienced, dedicated, and passionate.

Things to know for development

Pros

  • High performance with concurrency, and a huge featureset (you can do JOINs on arbitrary JSON fields…meaning your extract-transform-load loop that works on REST API data can be done fully in-database! _How cool is that _?!)

  • If you have specific requirements beyond CRUD apps (e.g. recursive queries, window functions, partial indexes, extensible data types), there's no better choice.

  • Great documentation.

Cons

  • Being good at writing optimised queries that receive exactly the data you need is critical.

  • One-process-per-connection architecture means maintaining TCP connections will be expensive operations (I use a postgREST server to create REST APIs though)

  • Self-hosting Postgres on something like EC2 will quickly become too expensive.

Serverless Databases

What Are Serverless Databases?

If full RDBMS like PostgreSQL are overwhelming or cost-prohibitive, managed serverless databases offered as-a-service might be to your liking. These relational databases will get you automated scaling to meet fluctuating demands and guaranteed uptime + fault tolerance, without any server wizardry on your part. All you bring to the dance is your code, and all you pay for is what you use.

How do I get started?

The How-to is the same with all of these. Sign up, choose a plan (all have free tiers), provision a DB, get the connection string, and you're good to go.

With that out of the way; let's talk about some serverless databases.

2. WunderBase

What is Wunderbase?

Honestly? The 'Easy Mode' for all your database needs. Here's the TL;DR :

  • A free and open-source serverless SQLite (!) database,

  • …using Prisma ORM for migrations using a schema,

  • …with a GraphQL API (so you get real-time Subscriptions out-of-the-box),

  • …running on a Fly Machine (Firecracker VM with a REST API),

  • …all behind an elegant, lightweight proxy written in Golang that starts up the VM (with cold lambda start times of 300–500ms) on receiving a network request, and turns it off automatically 10 seconds (configurable) after the last request.

How do I get started?

Dead simple. Deploy a Docker image (that you technically won't even need to build yourself; Get it here) to a fly.io machine with a volume attached, and you're done! Instructions for trying it out locally are here.

Remember, though: WunderBase does give you a GraphQL API, but making it public could be a security/performance concern. Use it with an API gateway, instead. (As mentioned before, Wundergraph, from the same devs, works perfectly.)

What's DevEx like?

First of all, a confession: I was a bit sceptical about fullstack development using SQLite, of all things. But between trying out WunderBase and reading this piece from LiteStream creator @benbjohnson, I've come around. Most web apps are read-heavy rather than write-heavy, and SQLite — by extension, WunderBase — fits these like a hand-in-glove, running as a self-contained, zero-configuration, in-process SQL "server".

I've found WunderBase great for prototyping ideas, or for (finally!) getting that personal weekend project up and running (storage needs <1 GB; with low traffic). It's quick and easy to set up both locally and for production.

What excites me most, though, is how WunderBase takes advantage of Fly Machines + SQLite being the only real 'serverless' database. Pretty much every serverless relational DB has a minimum monthly cost, even if you never use it…but since a SQLite database is literally just a binary file sitting in a volume, WunderBase can scale to 0 by simply shutting down the Fly.io VM when not serving requests. Costs are always a factor, and this way you can keep Wunderbase-backed apps as close to free as possible.

Things to know for development

Pros

  • Quick to set up; specialises in use-cases needing orders-of-magnitude more reads than writes.

  • Runs on a Firecracker VM on fly.io so you're dealing in stateless HTTP instead of maintaining TCP connections — possible to deploy WunderBase-backed apps to multiple edge locations around the world, for latencies of <100 ms.

  • Can truly scale to zero — fly.io pricing means you pay nothing if you aren't using it.

  • Native GraphQL API.

  • Wunderbase uses Prisma as an ORM, so you could always swap out SQLite for literally any other relational DB by editing the prisma.schema file.

Cons

  • SQLite's single-writer-multiple-readers model is not ideal for webapps that have multiple users interacting and performing changes.

  • Will no longer stay inexpensive if your needs involve large amounts of data or high traffic.

  • No out-of-the-box backups yet, but you could always use LiteStream to stream SQLite changes to AWS S3, Azure Blob Storage, Google Cloud Storage, SFTP, or NFS.

3. PlanetScale

PlanetScale is a relational database using MySQL, battle-tested Vitess (YouTube uses this to scale via sharding), and an innovative technique called database branching — bringing Git-style branches and merges to schema migration. Don't sweat the MySQL vs PostgreSQL debate : either will serve you well.

What's DevEx like?

As a developer, PlanetScale's Killer Feature is clearly the branching. If I can treat my database like code; change it, make feature/test branches, and do rollouts as I do code, you have my attention. It breaks your brain a little at first, but if you've ever used the Git workflow you'll feel quickly at home.

The absence of Foreign Key constraints was surprising and limiting, however, even if they did have guides to get around it. The bigger issue was TCP connections only, and since PlanetScale is MySQL, I couldn't use postgREST to generate RESTful APIs either. That was a bummer.

Things to know for development

Pros

  • Very performant, very elastic. I could focus on my app code and forget about scaling.

  • With the branching mechanism, it was intuitive to version control my schema as I do my code.

Cons

  • No foreign keys. Like, at all.

  • TCP connections only, so can't be used from Cloudflare Workers/Vercel Edge platforms.

  • Minimum monthly pricing beyond the limited free tier, even if you never do any reads/writes.

4. Fauna

Fauna is a distributed document-relational database that aims to offer the best of both SQL (relational modelling) and NoSQL (flexibility, speed) worlds. It offers GraphQL out of the box and a proprietary query language (FQL) that can do complex conditional transactions/reads in one go.

What's DevEx like?

The FQL itself (being language-specific DSLs) reminded me of RethinkDB (which I used to love, RIP 🖤), but what I found most interesting about Fauna was the fact that it's a geographically distributed database — I could automatically partition and distribute my data to multiple regions, meaning my data would be as close to my users as my app was — making it a hand-in-glove fit for the serverless/edge era of Vercel and Netlify.

Very fun to work with on the whole, but from the POV of someone who still writes queries, I'd think twice about integrating it in anything that's not a greenfield project since it doesn't use any standard SQL.

Things to know for development

First of all: while Fauna does give you a native GraphQL API, making it client facing could be a bad idea from a performance/security POV. Use it with an API gateway, instead. (Something like Wundergraph works well for this, and pairs very well with any RDBMS, PlanetScale, Fauna, MongoDB, and more.)

Pros

  • Native GraphQL API means Fauna is great if you're a JAMStack dev as many SSGs use GraphQL as their data layer (Gatsby, RedwoodJS)

  • Distributed database + native integrations for Vercel and Netlify makes Fauna a database happy path for the serverless/edge era.

Cons

  • If your project already uses SQL, integration might be difficult since Fauna uses a proprietary query language, FQL (with a GraphQL option) instead. If you're using WunderGraph though, this is a solved problem — as it can consolidate all your data sources into a single virtual graph layer that you can then access client-side via a secure, typesafe JSON-over-RPC API.

  • Again, a minimum monthly pricing beyond the free tier.

5. SupaBase

SupaBase aims to be the "open source Firebase alternative", and is a full suite of dev tools — Postgres as the datastore, postgREST under the hood for RESTful APIs, GoTrue (from Netlify) for Auth, an open-source server for realtime updates over websockets, an S3-compatible object storage, and edge functions via Deno servers — all presented to you in a unified, dashboard-y experience.

What's DevEx like?

It works well as a Firebase alternative, though feature parity is a little ways off, and there is no cross-compatibility between Firebase and SupaBase data. The native REST API is very useful for me because I host most of what I build on Vercel/Netlify.

Unfortunately, type safety is a concern with the JS client; generating types from the schema requires a third-party CLI tool. Until native typegen, I'd recommend using it with Prisma + tRPC for end-to-end typesafety.

Things to know for development

Pros

  • A ton of features besides just the database.

  • Provides a RESTful API using postgREST, very useful if you want to use SupaBase from serverless/cloud functions.

  • Can be self hosted — with some difficulty at the moment (unclear docs).

Cons

  • Type safety is a concern. (Might be better with future v2 client)

  • Again, minimum monthly pricing beyond the limited free tier.

6. MongoDB

What is MongoDB?

The de facto NoSQL option for most people — the MERN stack is how most people got started with web development, to begin with. The ubiquitous M — MongoDB — is a cross-platform, source-available database that saves its data as (essentially) JSON documents, rather than interconnected tables with relations between them.

How do I get started?

Self-host on a VPS, or take their managed MongoDB Atlas option.

What's DevEx like?

I've been using MongoDB for some years now and it *actually *is faster than relational databases if (and only if) you know your data can always be represented as a CSV file, and all you'd need is additional features on top — like the ability to theoretically scale infinitely.

It's also well integrated with JavaScript and JSON — staples for web devs. Personal preference, but I find that the syntax, for example — db.collection().find({}) — lends itself well to copy-pastes between IDE and Shell while testing. I didn't even need to use Mongoose.

Things to know for development

Pros

  • Perfect fit when you use it for its intended purpose — as a document store, for non-relational data.

  • There's an active community for it, tons of tutorials and resources, and even an ORM (Mongoose) if you need one.

  • The managed option, Atlas, has a serverless plan that is pay-per-operation so you can scale to zero and never pay anything if you don't use it.

  • Out-of-the-box real-time updates, logging, and automation.

Cons

  • Not relational.

  • Atlas can be slow with certain regions.

  • Not truly open-source; for anything but private non-commercial use of their source code you'll have to release yours in full — including code for every other service you used, which might make it a non-starter.

7. Redis/Workers KV

What are Redis and Workers KV?

These are special databases with tiny but insanely fast storage that can only store key/value data. Essentially: very big hash tables that are network connected, with the added advantage that they can live entirely in memory (but can persist to a connected volume if you need them to).

How do I get started?

For Cloudflare Workers KV, sign up here. For Redis, your options include a managed Redis-as-a-service from DigitalOcean/Vultr/Upstash, or just throwing the official Redis docker image on a VPS and hosting it yourself.

What's DevEx like?

Fantastic for very specific use cases that prioritise low latency over everything else. Use them if your data can be represented by a hash table of 1:1 data mappings (userID to social media profile URL, for example). If so, congratulations! Now your lookup has become an O(log(n)) or even an O(1) operation instead of O(N). That's wild.

Want to know quickly if Bob follows Alice? Want to keep a list of the latest posts on your site instead of querying it from an API/RSS feed every single time? Want to persist orders for your eCommerce site as a customerID → itemID mapping until the IPN confirmation from Paypal/Stripe comes in?

These high-performance + low latency Key-Value stores — especially vendors that provide it as-a-service at edge locations — are perfect for your needs, then.

Things to know for development

Going to skip pros/cons here since K/V stores are so simple, but here's a common gotcha: if you're using a managed Redis-as-a-service, first make sure they're compatible with the parts of the Redis API you'll need (For example, many providers do not yet support the Geo core).

Conclusion

Reading this has hopefully helped you overcome decision fatigue, by realising that the question isn't so much "which database is the best?" as it is "which database will solve this specific problem I have the best?".

So with that approach in mind, here's the rundown:

  • "I need something quick, easy, and cost-effective that can scale to >1 and 0" → Wunderbase.

  • "I need to model real-world data." → You'll need a relational DB. Use PlanetScale / Fauna / SupaBase, or host Postgres if you already have the expertise/resources in place.

  • "I need real-time updates." → WunderBase (via GraphQL Subscriptions), SupaBase, Fauna (via Event Streaming), and MongoDB all offer this. If you only need key-value pairs, Redis has built-in pub/sub.

  • "Low latency is critical for my use case." → KV stores provided at-the-edge like Upstash (Redis), or Cloudflare Workers KV.

  • "I'm heavily invested in GraphQL." → Fauna or WunderBase — preferably with an API gateway using WunderGraph, instead of exposing a public GraphQL endpoint.

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics