@specific.dev/replacebase
v0.3.1
Published
Drop-in replacement for Supabase's backend as a Typescript library
Downloads
243
Readme
Replacebase
Replacebase is a library to help you migrate away from Supabase over to backend infrastructure that you control. It's a simple Typescript library that wraps your Postgres database and S3 storage, and exposes a Supabase-compatible API. This means you don't have to change any frontend logic and can unify all your backend code for a simpler architecture.
There are many reason to use Replacebase:
- Host your backend where you like, for example on AWS or Specific
- Reduce your dependency on Supabase services and their uptime
- Use a better database and storage provider, like Planetscale or Specific
- Gradually migrate away from using Supabase SDKs to a more flexible backend architecture that you control
- Replace inflexible Supabase services with better alternatives, like Better Auth
Replacebase implements many parts of Supabase (with more to come):
- [x] REST API (can connect to any Postgres database)
- [x] Auth (built on Better Auth)
- [x] Storage (can connect to any S3-compatible service)
- [x] Realtime (broadcast and presence)
- [x] RPC
- [ ] Edge functions
- [ ] Vectors
This is an early-stage project, use it with care and test thoroughly before using in production
Installation
npm install @specific.dev/replacebaseGetting started
For this guide, we will use your existing Postgres database and Supabase-provided S3-storage and connect Replacebase.
We also offer a skill to let your coding agent help with the migration: npx skills add specific-dev/replacebase
1. Get your Supabase details
Sign in to your Supabase account and retrieve the following:
Your Postgres connection string (click "Connect" in the top bar)
Your JWT Signing Key URL (go to "Settings" -> "JWT Keys" -> "View key details" -> "Discovery URL")
Your legacy JWT secret (go to "Settings" -> "JWT Keys" -> "Legacy JWT Secret")
If using storage, your S3 connection details and access key (go to "Storage" -> "S3")
2. Serve up Replacebase
On your backend, initialise Replacebase with the details from step 1.
If you don't have anywhere to host your backend yet, we recommend Specific
// server.ts
import { createReplacebase } from "replacebase";
const replacebase = await createReplacebase({
databaseUrl: process.env.DATABASE_URL!, // Supabase Postgres connection string
jwksUrl: process.env.JWKS_URL!, // Supabase JWT Signing Key URL
jwtSecret: process.env.JWT_SECRET!, // Supabase JWT secret
// If using storage, pass Supabase S3 details
storage: {
s3: {
endpoint: process.env.S3_ENDPOINT!,
region: process.env.S3_REGION!,
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
},
},
});Next you need to serve up the APIs that Replacebase exposes. Replacebase is framework-agnostic and works with any web server. Pick whichever fits your stack:
Since Next.js catch-all routes are mounted under a subpath, use the basePath option so Replacebase matches routes correctly:
// app/api/[...path]/route.ts
const replacebase = await createReplacebase({
// ...
basePath: "/api",
});
export const GET = replacebase.fetch;
export const POST = replacebase.fetch;
export const PUT = replacebase.fetch;
export const PATCH = replacebase.fetch;
export const DELETE = replacebase.fetch;Note: Next.js API routes don't support WebSockets, so Realtime won't work with this setup. If you need Realtime, run Replacebase as a separate backend service.
import express from "express";
const app = express();
app.all("/*", replacebase.toNodeHandler());
const server = app.listen(3000);
replacebase.injectWebSocket(server); // Enables Realtime (broadcast + presence)export default { fetch: replacebase.fetch };For Realtime support on Node.js, use @hono/node-server to get an HTTP server you can inject WebSockets into:
import { serve } from "@hono/node-server";
const server = serve({ fetch: replacebase.fetch, port: 3000 });
replacebase.injectWebSocket(server);3. Update your client config
The only change you need to make on your frontend is to connect to your own backend with Replacebase instead of Supabase.
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(
-"https://xyz.supabase.co",
+"http://replacebase-api.spcf.app", // Insert wherever your Replacebase is served from
// ...
);That's it, test it out!
Next steps for migration
Replacebase is designed to be a stepping stone to a larger migration away from Supabase. Depending on your goals, you probably want to continue your migration by doing the following:
Change Postgres provider
Since Replacebase connects to any standard Postgres database, you can move off Supabase's hosted Postgres whenever you're ready. Spin up a database on AWS RDS, Specific, or any other provider, migrate your data with pg_dump/pg_restore, and update your DATABASE_URL. Your frontend code will keep working without changes.
Change storage provider
Replacebase works with any S3-compatible storage service. You can switch from Supabase's built-in storage to AWS S3, Cloudflare R2, Specific, or any other provider simply by updating your credentials. Migrate existing files with a tool like rclone or the AWS CLI.
Migrate away from the Supabase SDK
Once Replacebase is running, you can start building regular backend API endpoints alongside it. For example, replace a Supabase client query like supabase.from("posts").select() with a call to your own /api/posts endpoint. With Replacebase, you can do this gradually to move towards a more flexible backend design that better fits your product. Eventually, you can drop @supabase/supabase-js and Replacebase from your stack entirely!
License
MIT
