Backend options for teams that started on Appwrite and need a different data model, hosting setup, or more control over their backend.
Appwrite is an open-source backend that bundles auth, databases, storage, functions and realtime behind its own APIs and client SDKs, and teams can use the managed cloud or self-host it as a set of Docker containers. It starts to hurt when the backend grows past what fits in Appwrite Functions, when the team wants plain SQL against the data, or when the backend has to run inside the company's own AWS or GCP account, because none of those fit neatly inside the bundle. This article compares the options teams usually look at next, which are Encore, Supabase, Firebase, PocketBase, Nhost and Convex.
Reasons teams look for Appwrite alternatives:
Encore combines backend code and infrastructure for projects that have grown past the point where Appwrite functions wrapped around platform APIs are enough, so you write the services and APIs in TypeScript or Go and declare the Postgres databases, Pub/Sub topics, buckets, cron jobs and secrets in the same code, encore run starts all of it locally (Postgres runs in Docker), and a deploy creates the same resources in your own AWS or GCP account.

An existing Appwrite login can keep working while the backend moves, because the client sends the JWT from account.createJWT() and an Encore auth handler checks it by calling Appwrite before any authenticated endpoint runs, and those endpoints can then query a Postgres database declared in the same service.
import { api, APIError, Gateway, Header } from "encore.dev/api";
import { authHandler } from "encore.dev/auth";
import { getAuthData } from "~encore/auth";
import { SQLDatabase } from "encore.dev/storage/sqldb";
import { Account, Client } from "node-appwrite";
interface AuthParams { authorization: Header<"Authorization">; }
interface AuthData { userID: string; email: string; }
// Checks the Appwrite JWT by calling GET /account with it.
export const auth = authHandler<AuthParams, AuthData>(async ({ authorization }) => {
const client = new Client()
.setEndpoint(process.env.APPWRITE_ENDPOINT ?? "https://cloud.appwrite.io/v1")
.setProject(process.env.APPWRITE_PROJECT_ID ?? "")
.setJWT(authorization.replace(/^Bearer /, ""));
try {
const user = await new Account(client).get();
return { userID: user.$id, email: user.email };
} catch {
throw APIError.unauthenticated("invalid Appwrite JWT");
}
});
export const gateway = new Gateway({ authHandler: auth });
// Postgres runs in Docker with `encore run` and on RDS or Cloud SQL when deployed.
const db = new SQLDatabase("notes", { migrations: "./migrations" });
interface Note { id: number; body: string; }
export const listNotes = api(
{ expose: true, auth: true, method: "GET", path: "/notes" },
async (): Promise<{ notes: Note[] }> => {
const { userID } = getAuthData()!;
const rows = db.query<Note>`SELECT id, body FROM notes WHERE owner_id = ${userID}`;
const notes: Note[] = [];
for await (const row of rows) notes.push(row);
return { notes };
},
);
encore run starts the services and their infrastructure locally, and the local development dashboard shows a trace of each request, so a change can be tested end to end before it is deployed.Encore does not include a hosted user directory or sign-in UI, so teams connect an identity provider through an authentication handler, and that provider can stay Appwrite Auth while the rest of the backend moves. There is also no automatic realtime sync to clients, so teams either build it with streaming APIs or keep Appwrite Realtime for it. Migrating is a code change, and since adoption can be incremental most teams start with one API or background job.
See how to migrate Appwrite to AWS.
Run in your terminal to get started locally.
Supabase combines Postgres with authentication, storage, realtime and Edge Functions, so you get a relational model with tables, foreign keys, joins and SQL transactions, and the client SDKs talk to the bundled services.
Supabase is the closest swap for teams that want a bundle like Appwrite with SQL at the center, where Appwrite permissions become RLS policies and client calls move to Supabase's SDK. Like Appwrite it can be self-hosted, which comes with the same operational responsibility.
Firebase combines authentication, databases, storage, functions and hosting with mobile tools such as Crashlytics and Remote Config, and Firestore supports realtime listeners and offline client access.
Firebase fits teams that care most about mobile tooling and offline sync and are comfortable with Google's ecosystem and usage billing. It is only available as a managed service, so teams that chose Appwrite because they could self-host it would lose that option.
PocketBase packages a SQLite database, authentication, file storage, an admin UI and realtime subscriptions into a single executable.
PocketBase is much lighter to self-host than Appwrite and fits small apps on one server well, although that single-server design becomes the limit once you need services that scale independently. Its documentation also advises against production-critical use while compatibility changes can still require manual migrations.
Nhost is a Postgres backend platform with an instant GraphQL API, authentication, storage and serverless functions in JavaScript or TypeScript, and it can also run your own containers.
Nhost fits teams that want Postgres and GraphQL out of the box, and since permissions are defined on the GraphQL layer, Appwrite permission rules have to be rewritten there. Its ecosystem is smaller than that of Supabase or Firebase.
Convex puts backend operations in TypeScript queries, mutations and actions, and its query subscriptions update connected clients when the data changes.
Convex fits apps where realtime behavior is central, but data moves into Convex's document model and logic into its function runtime, so migrating from Appwrite means reworking both. It can run on the managed platform or be self-hosted.
Teams usually move one part at a time, so an Encore service can take over the APIs and background jobs that have outgrown Appwrite Functions while Appwrite keeps handling auth and storage. The quickstart walks through a first service.
Encore for a backend with services and infrastructure in your own AWS or GCP account, Supabase for a Postgres-based BaaS, Firebase for mobile apps and offline sync, PocketBase for small apps on one server, Nhost for Postgres with a GraphQL API, and Convex for reactive TypeScript applications.
Both bundle auth, database, storage, functions, and realtime, and both can be self-hosted. Supabase is built directly on Postgres, so you work with SQL, Row-Level Security, and standard Postgres tools. Appwrite exposes its databases through its own APIs and SDKs (TablesDB and DocumentsDB) rather than through a raw SQL connection.
It runs as a set of Docker containers, so getting started is quick. Running it in production means you own upgrades, data migrations between versions, backups, monitoring, and scaling for the whole platform.
Yes. The client calls account.createJWT() and sends the token to your API. Appwrite does not publish a JWKS, so the backend checks the token by calling Appwrite with it, for example account.get() in node-appwrite after client.setJWT(jwt). In Encore that call goes in an auth handler. The JWT expires after 15 minutes, so the client has to refresh it, and every authenticated request adds a round trip to Appwrite unless you cache the result.
Export data through Appwrite's APIs, map collections or tables to the target schema, and replace client SDK calls with the new backend's APIs. Users, storage files, and functions each need their own migration step. See our guides for moving Appwrite to AWS or GCP.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.