Bỏ Supabase: Railway PostgreSQL Prisma cho Indie Hacker

P P T P Chung

Thay thế Supabase bằng Railway + PostgreSQL + Prisma: backend linh hoạt cho indie hacker

Supabase rất tốt để bắt đầu nhanh: database PostgreSQL, auth, storage, realtime, dashboard đẹp, API tự sinh. Với indie hacker, nó giúp ship MVP cực nhanh. Nhưng sau vài dự án, nhiều người gặp cùng một câu hỏi: nếu mình muốn backend linh hoạt hơn, kiểm soát logic sâu hơn, deploy API riêng, schema rõ hơn, ít phụ thuộc platform hơn thì sao?

Một hướng thay thế đáng cân nhắc: Railway + PostgreSQL + Prisma.

Combo này không cố “clone” Supabase. Nó chọn hướng khác: tự sở hữu backend hơn, vẫn nhanh, vẫn cloud-native, vẫn phù hợp solo founder. Railway lo hạ tầng/deploy. PostgreSQL lo dữ liệu. Prisma lo ORM, migration, type-safe DB access. Phần còn lại — auth, business logic, API — bạn tự thiết kế theo nhu cầu.

Kết quả: backend ít “magic”, dễ mở rộng, dễ debug, dễ migrate.


Vì sao indie hacker muốn rời Supabase?

Supabase mạnh, nhưng không phải lúc nào cũng khớp.

1. Logic backend phức tạp hơn CRUD

Ban đầu app chỉ cần:

– tạo user – lưu profile – insert order – hiển thị dashboard

Supabase xử lý tốt. Nhưng khi sản phẩm lớn hơn, bạn có thể cần:

– xử lý webhook Stripe – chạy background job – validate nghiệp vụ phức tạp – phân quyền theo team/workspace – audit log – rate limit – queue email – sync data từ API ngoài – custom API response

Lúc này, viết logic rải rác qua edge function, SQL policy, trigger, client SDK có thể khiến kiến trúc khó theo dõi.

2. RLS mạnh nhưng dễ khó debug

Row Level Security là điểm mạnh của Supabase. Nhưng nếu policy phức tạp, bug auth/data permission có thể rất mệt:

– query không trả dữ liệu → do policy? – insert fail → do role? – user thấy thiếu row → do claim? – local khác production → do config?

Với backend tự viết, permission nằm trong code server. Ít “ẩn” hơn. Dễ log, test, review.

3. Muốn tránh lock-in ở tầng platform

Supabase dựa trên PostgreSQL, nên không lock-in dữ liệu nặng như Firebase. Nhưng vẫn có lock-in ở:

– auth model – edge function convention – storage API – realtime – dashboard workflow – client SDK pattern

Railway + PostgreSQL + Prisma giúp stack gần chuẩn hơn:

– DB: PostgreSQL thường – ORM: Prisma – API: Express/Fastify/NestJS/Next.js route – Auth: tự chọn – Deploy: container/app service

Dễ chuyển sang VPS, Fly.io, Render, AWS, GCP hơn.


Railway + PostgreSQL + Prisma là gì?

Railway

Railway là platform deploy app + database cực nhanh. Bạn có thể:

– deploy Node.js backend từ GitHub – tạo PostgreSQL bằng vài click – quản lý env var – xem logs – scale service – chạy migration – preview deployment

Với indie hacker, Railway giống “Heroku hiện đại”: ít DevOps, đủ linh hoạt.

PostgreSQL

PostgreSQL là DB quan hệ mạnh, ổn định, phổ biến. Dùng Postgres giúp bạn có:

– relational model rõ – transaction – index – JSONB nếu cần linh hoạt – full-text search cơ bản – constraint dữ liệu – ecosystem lớn

Đây cũng là DB Supabase dùng bên dưới. Chuyển sang Railway không phải đổi tư duy dữ liệu quá nhiều.

Prisma

Prisma là ORM cho Node.js/TypeScript. Điểm mạnh:

– schema rõ trong schema.prisma – migration có version – query type-safe – auto-complete tốt – relation dễ đọc – giảm SQL boilerplate

Ví dụ model:

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  projects  Project[]
  createdAt DateTime @default(now())
}

model Project { id String @id @default(cuid()) name String ownerId String owner User @relation(fields: [ownerId], references: [id]) createdAt DateTime @default(now()) }

Schema → migration → DB → type-safe client.


Kiến trúc đề xuất

Một stack đơn giản:

Frontend: Next.js / Nuxt / Remix / React – Backend API: Node.js + Express/Fastify/NestJS – DB: Railway PostgreSQL – ORM: Prisma – Auth: Auth.js, Clerk, Better Auth, Lucia-style custom, JWT/session – Payment: Stripe webhook trong backend – Jobs: BullMQ/Redis, hoặc cron Railway, hoặc external queue – Storage: S3/R2/UploadThing

Luồng cơ bản:

1. User login → auth provider/session 2. Frontend gọi API backend 3. Backend kiểm tra session 4. Backend xử lý permission/business logic 5. Prisma query PostgreSQL 6. API trả JSON

Điểm chính: client không nói trực tiếp với DB. Backend là cổng kiểm soát.


Setup nhanh Railway + PostgreSQL + Prisma

1. Tạo backend Node.js

Ví dụ với Express:

mkdir indie-backend
cd indie-backend
npm init -y
npm install express dotenv @prisma/client
npm install -D typescript tsx prisma @types/node @types/express
npx tsc --init
npx prisma init

2. Tạo PostgreSQL trên Railway

Trên Railway:

– New Project – Add PostgreSQL – Copy DATABASE_URL – Add service backend từ GitHub – Set env var DATABASE_URL

Local .env:

DATABASE_URL="postgresql://user:password@host:port/db"

3. Định nghĩa Prisma schema

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client { provider = "prisma-client-js" }

model User { id String @id @default(cuid()) email String @unique name String? createdAt DateTime @default(now()) }

4. Chạy migration

npx prisma migrate dev --name init

Production:

npx prisma migrate deploy

Nên thêm script:

{
  "scripts": {
    "dev": "tsx src/server.ts",
    "build": "tsc",
    "start": "node dist/server.js",
    "postinstall": "prisma generate",
    "migrate": "prisma migrate deploy"
  }
}

5. API mẫu

import express from "express";
import { PrismaClient } from "@prisma/client";

const app = express(); const prisma = new PrismaClient();

app.use(express.json());

app.get("/users", async (req, res) => { const users = await prisma.user.findMany({ orderBy: { createdAt: "desc" } });

res.json(users); });

app.post("/users", async (req, res) => { const { email, name } = req.body;

const user = await prisma.user.create({ data: { email, name } });

res.status(201).json(user); });

app.listen(process.env.PORT || 3000);

Đơn giản, rõ, dễ debug.


So sánh Supabase vs Railway + PostgreSQL + Prisma

Supabase phù hợp khi

– cần MVP rất nhanh – muốn auth/storage/realtime sẵn – app thiên về CRUD – team nhỏ, chưa muốn viết backend nhiều – thích client SDK gọi trực tiếp DB qua policy – realtime là feature cốt lõi

Railway + PostgreSQL + Prisma phù hợp khi

– muốn backend riêng – logic nghiệp vụ phức tạp – cần custom auth/permission – có webhook/payment/job – muốn API ổn định cho web/mobile – muốn dễ migrate hạ tầng – thích TypeScript full-stack – muốn test logic server rõ ràng

Tóm gọn:

Supabase → tốc độ ban đầu. Railway + Prisma → kiểm soát dài hạn.

Auth: phần cần tính kỹ nhất

Supabase có auth tích hợp. Khi rời Supabase, bạn cần chọn auth riêng.

Các lựa chọn phổ biến:

Auth.js

Phù hợp nếu dùng Next.js, muốn OAuth/session linh hoạt. Tự host, kiểm soát tốt. Nhưng cần hiểu session/callback/provider.

Clerk

Rất nhanh, dashboard tốt, UX đẹp. Phù hợp indie hacker muốn tiết kiệm thời gian. Đổi lại: phụ thuộc SaaS auth.

Better Auth

Đang được cộng đồng TypeScript chú ý. Hợp nếu muốn auth hiện đại, tự host nhiều hơn.

Custom auth

Chỉ nên làm nếu bạn hiểu security: password hashing, session rotation, CSRF, reset password, email verification. Với indie hacker, thường không nên tự viết từ đầu nếu không cần.

Khuyến nghị thực tế: dùng Clerk/Auth.js trước, đừng lãng phí 2 tuần vào auth nếu sản phẩm chưa có user trả tiền.


Migration từ Supabase sang Railway

Nếu đang dùng Supabase PostgreSQL, chuyển dữ liệu khá thẳng:

1. Export schema/data từ Supabase. 2. Tạo PostgreSQL trên Railway. 3. Import dump. 4. Tạo Prisma schema bằng introspection:

npx prisma db pull
npx prisma generate

5. Refactor code từ Supabase client sang Prisma query trong backend. 6. Thay auth/storage/realtime bằng giải pháp tương ứng.

Điểm khó không phải database. Điểm khó là những thứ Supabase cung cấp ngoài DB:

– auth users – RLS policies – storage buckets – edge functions – realtime subscriptions

Vì vậy, nên migrate theo module. Đừng “big bang” nếu app đang có user thật.


Best practices cho indie hacker

1. Giữ schema đơn giản

Đừng over-engineer. Bắt đầu với vài bảng rõ:

– User – Account/Workspace – Project – Subscription – Event/Log

Constraint tốt hơn validation rải rác.

2. Dùng migration nghiêm túc

Không sửa DB production bằng tay nếu có thể tránh. Dùng:

npx prisma migrate dev
npx prisma migrate deploy

Migration → lịch sử rõ → rollback dễ hơn.

3. Log lỗi backend

Railway logs hữu ích, nhưng nên thêm structured logging nếu app lớn:

– request id – user id – endpoint – error stack – duration

Debug nhanh → tiết kiệm ngày công.

4. Tách service theo nhu cầu, không quá sớm

Ban đầu, một backend monolith là đủ. Khi cần mới tách:

– worker – cron – webhook handler – admin API

Indie hacker cần revenue, không cần microservices sớm.

5. Theo dõi chi phí

Railway tiện nhưng chi phí có thể tăng nếu app chạy nhiều service. Theo dõi:

– DB size – compute hours – outbound traffic – logs – backup

Tối ưu sau khi có traction, không tối ưu trước MVP.


Khi nào không nên thay Supabase?

Không cần đổi nếu:

– Supabase đang chạy ổn – bạn dùng nhiều realtime – auth/storage/RLS đã ổn định – app chưa có logic backend phức tạp – migrate làm chậm roadmap kiếm tiền – team chưa quen DevOps/backend

Đổi stack chỉ vì “cooler” là sai. Stack tốt là stack giúp ship nhanh, ít lỗi, dễ kiếm tiền.


Kết luận thực tế

Railway + PostgreSQL + Prisma là lựa chọn rất hợp cho indie hacker muốn backend linh hoạt hơn Supabase nhưng chưa muốn tự quản server. Bạn có PostgreSQL chuẩn, deploy nhanh, ORM type-safe, API tự kiểm soát, business logic rõ trong code.

Đổi lại, bạn phải tự quyết nhiều hơn: auth, permission, storage, realtime, jobs. Supabase cho bạn một “backend platform” hoàn chỉnh. Railway + Prisma cho bạn “hạ tầng nhẹ + quyền kiểm soát”.

Nếu đang ở giai đoạn MVP đơn giản, Supabase vẫn tuyệt vời. Nếu sản phẩm bắt đầu có billing, webhook, team permission, workflow phức tạp, API riêng, hoặc nhu cầu tránh platform coupling, combo Railway + PostgreSQL + Prisma đáng thử.

Lời khuyên ngắn: đừng migrate vì công nghệ. Migrate vì sản phẩm cần kiểm soát hơn.

Tác giả

P T P

Chia sẻ

Bài viết liên quan

Bình luận (0)

Email của bạn sẽ không được hiển thị công khai.

Chưa có bình luận. Hãy là người đầu tiên!