
Why I picked Convex over Firebase, Supabase, and Neon for my app

Why I picked Convex over Firebase, Supabase, and Neon for my app is a guest Stack Post from the community Convex Champion, Matt Luo.
For my startup, I didn’t immediately choose Convex. I evaluated many databases along the way. And like many, I was concerned about building on top of a relatively new database. Let me walk through some other databases that I had evaluated, and describe how I ultimately decided to use Convex.
This decision process started in early 2024. I was looking for a database for my language learning app, LanguageHopper.com. I wanted to build a messaging app based on the interlinear format for language learning.
The other databases I evaluated were: Firebase, PlanetScale, Supabase, and Neon, in this order.
Firebase had significant limitations
I started with Firebase, the back end as a service which includes Firestore and Firebase realtime database. I really wanted Firebase to work. I even embraced Flutter to increase the probability that the tech stack would work.
There were significant problems:
- Flutter web was just not ready for a commercial production app. I used Flutter version 3.13.0. There were many problems with scrolling and selecting text. The “uncanny valley” UX feeling was strong. This UX experience does not relate to the database of Firestore per se, but it made me feel like official products in the Firebase ecosystem were being announced as more ready than they actually were.
- Important aspects of Firebase were getting replaced with Google Cloud Platform services. This created a disjointed developer experience, and it made me feel like Google was looking to terminate, or at least stop focusing on, Firebase. A couple important examples include Firebase Auth being replaced with a general GCP identity auth service as well as Firebase Functions becoming a wrapper for GCP Cloud Run. Based on Hacker News and Twitter posts, I speculate that there was significant organizational turnover and internal politics within the Firebase/Flutter organization.
- There were just too many bugs in the developer’s happy path to deploying the application, particularly for the cloud run services. The CLI for the cloud run services provided very little, and often misleading error messages when it failed to run.
- The Firebase Auth UI SDK had not been updated for years.
- Firebase’s free customer support seems to only respond during the India time zone. And the initial paid tier for GCP support seemed really expensive.
PlanetScale had limited foreign language support
I next looked for a traditional relational database. My prior career experience was mostly MySQL and MariaDB, so I was naturally drawn to PlanetScale. I thought PlanetScale had a great blog, good documentation, an interesting pitch: MySQL, on Vitess, so the developer never needs to worry about the connection pool being too small.
I coded an initial version of the app using Drizzle as an ORM for PlanetScale.
I ran into a couple of issues:
- MySQL had limited database collation options. So, I thought I was going to run into problems down the road with MySQL for a language learning use case.
- While I was trying PlanetScale, the company removed the free tier. Regardless of whether I was going to pay for the pro tier, it seemed like it was going to be difficult for a small account to get customer support. There didn’t seem to be a public developer community for PlanetScale.
Supabase entailed too much SQL
I then looked at Supabase, the “open source Firebase alternative”. I thought Supabase had an interesting pitch: if you want “just Postgres”.
From my read of their blog, the backend as a service was based on open source parts. That made it look easy to migrate from in case I wanted to in the future. I searched around and found some customer stories of migrating out, like Val Town’s big Hacker News post about leaving Supabase.
Supabase reminded me of my past employer, Goldman Sachs. Goldman staff often stitched together a bunch of popular, open-source products for an app, and then reuse that architecture for ancillary apps in its division. It was good execution on existing tech. But the contributors of those individual components didn’t have the other components in mind. For example, Elixir/Phoenix contributors don’t necessarily coordinate with Postgres contributors.
I never actually reached the point where I started a Supabase project and coded with it. While I was researching and reading about Supabase, I ran into some issues:
- It seemed like a lot could go wrong as a Supabase project gets more complex. From reading the documentation, it looked like a lot of happy path workflow functionality was supposed to be coded as SQL triggers. In my past experience with workflow apps, developers used SQL triggers as a workaround to make some sort of asynchronous call. It was difficult to comprehend the codebase. In workflow apps, it is really important to understand how data gets updated in the database.
I may very well have incorrectly interpreted the spirit of how to design a Supabase app from reading the documentation. But my general impression was that a lot of business logic manifested as SQL. It seemed like many important aspects to a Supabase project, like row level security, used SQL significantly.
- It seemed like the price of Supabase quickly increases. For example, I recall that the price to get a SOC compliant certificate was $600. I was (and still am) new to SOC related pricing, but that seemed high to me at the time.
Zooming out, I liked the core idea of Supabase: that Supabase’s bundling of popular components was more synergistic than if I tried to integrate them on your own. The value proposition appealing to me. It was a large back end as a service that sat on top of AWS/Azure/GCP. Working directly on AWS has been slow for me in the past.
Neon had no native realtime features
I was attracted to Neon for database instance branching. Earlier in my career building CRM, customer servicing, and workflow apps, I know how hard it is find bugs from dev and synthetic data. Edge cases often surface up when the app is live in production.
Neon is based on Postgres, which seemed like it could accommodate more foreign language requirements than MySQL could.
I built another version of Language Hopper with Neon, using Drizzle as an ORM.
Here’s a summary from notable observations:
- As a developer using Neon, I had to choose a size of my database. So, it was not completely serverless, in the sense that sizing (and auto-scaling) was completely Neon’s responsibility.
- The word “neon” is a surprisingly common word in the Google search engine results page. This made finding content about Neon the database actually noticeably difficult. But it wasn’t as bad as it was with Stream, the chat SDK company. (I had also briefly tried Stream, after Firebase).
- Neon actually provides their own deployment of Postgres, and this deployment had limitations. Most notably, I could not install any Postgres extension. There was an allowlist of extensions I could install. I remember trying to install an extension specifically for full text search for Chinese, but it wasn’t on the roadmap to be added.
Neon’s a great service for what they advertise, which is a serverless PostgreSQL database with separated storage and compute. (This means that compute can truly go to zero, which Aurora could not at the time).
Ultimately, I realized I was shopping around for the wrong thing. I asked Neon dev relations how to make my front end realtime. I had a long roadmap of work ahead of me to do so. I was considering bringing in another vendor, Ably, into tech stack just for realtime syncing. But the setup was getting complicated fast.
Other notable databases I evaluated
Stream, the chat SDK, was the wrong layer of abstraction for my app.
I was granted a “Maker” organization account for startups to build on top of Stream. The most difficult thing about Stream was trying to find information outside of the Stream website about how to develop in Stream. I did not find any developer community. When I tried searching for Stream content, I would mostly return mostly unrelated search results. I had to add additional keywords like, getstream .io, but the search results were mostly not useful.
But even if I did find sufficient information to develop on my own, there was a fundamental problem that I was not the ideal customer of Stream’s. Stream’s SDK is an abstraction layer that is fundamentally about chat messages. The SDK had primitives such as “messages”, “groups”, and “authors”, etc. The pricing was also based on this abstraction, e.g. there was usage based pricing on the number of messages sent. So, Stream’s customer gets Stream’s particular implementation of a chat app. That didn’t work for me, since I was fundamentally trying to build my own chatting experience.
Xata seemed targeted to a citizen developer
Xata is a competitor to Neon, and they had a distinctive value proposition of including full text search as native feature. The starter plan also had a very large storage allowance.
When I evaluated it, the product seemed like it was still in early stages. There was no search capability with Asian languages, namely Chinese, Korean, and Japanese.
One thing that stood out to me was that the documentation and marketing copy seemed to target a less technical developer. Perhaps the target audience was a cross between a product manager and a software engineer. There were many analogies to starting a database as if a database table were a spreadsheet.
Nile was too early for me to start using it for my app
Nile seemed interesting in that it was the only major database startup to provide native multi-tenant app topologies. So, I imagine that a developer could use this to build a fleet of user defined applications. This was intriguing, but Nile was too early in its development and I didn’t have a strong need for multi-tenancy.
Convex was the best fit, primarily for my realtime needs
I initially tepidly checked out the Convex website in 2024. I bounced off. After seeing how much work it would take to build realtime capabilities myself, and came back to eat some humble pie. But now after using it for about year, I am fully embracing it.
After using trying it out for a few weeks, I understood Convex as a full backend as a service, built from the ground up for a modern TypeScript app. It felt like another attempt at making a Firebase, but with the ambition of a MongoDB to bring an opinion into this world.
I can’t remember exactly how I initially discovered Convex. Perhaps I Google searched, “Realtime database.” But in any case, when I first saw my front end sync with my manual change to the database, it was a moment of joy for me. Prior in my career, I always had to refresh the browser to see a change in my app.
The key reason I ultimately went with Convex is that my app needs a lot of distributed systems code that would be very difficult to build myself. For example, realtime sync, caching, abstractions to the database, type safety, the list goes on. Convex feels like hiring a backend staff on day one.
And looking toward the future, Convex has a lot going for it. More and more developers will discover the craftsmanship that goes into Convex’s abstractions, these ease of LLMs comprehending and coding a large codebase with Convex, and the simple yet powerful capabilities that come with Convex components.
Convex is the backend platform with everything you need to build your full-stack AI project. Cloud functions, a database, file storage, scheduling, workflow, vector search, and realtime updates fit together seamlessly.