Thay thế Supabase bằng PocketBase: hướng dẫn dựng backend nhẹ cho MVP trong 30 phút
Bạn đang làm MVP. Cần auth, database, file upload, admin UI, API realtime. Bạn nghĩ tới Supabase. Hợp lý. Nhưng đôi khi Supabase “quá nhiều”: Postgres, policy, migration, cloud config, pricing, edge function, bucket, env… Với MVP nhỏ, bạn chỉ cần backend chạy nhanh, dễ deploy, dễ hiểu, ít phụ thuộc.
PocketBase → lựa chọn rất đáng thử.Một file binary. DB SQLite. Admin dashboard có sẵn. REST API tự sinh. Auth built-in. Realtime built-in. File storage built-in. Deploy cực nhẹ. Dựng backend cho MVP trong khoảng 30 phút là thật, nếu scope rõ.
Bài này hướng dẫn cách dùng PocketBase thay Supabase cho MVP: khi nào nên dùng, setup, tạo schema, auth, API, upload file, deploy, ưu/nhược thực tế.
PocketBase là gì?
PocketBase là backend dạng “all-in-one” viết bằng Go, gồm:– SQLite database – Admin UI – REST API tự động – Realtime subscriptions – Authentication – File upload – Access rules – Backup/export – Có thể extend bằng Go hoặc JavaScript hooks
Khác Supabase: Supabase là nền tảng backend đầy đủ dựa trên Postgres. PocketBase nhỏ hơn, đơn giản hơn, chạy như một process duy nhất.
Cách hiểu nhanh:
– Supabase → “Firebase open-source + Postgres” – PocketBase → “SQLite backend đóng gói trong 1 binary”
Nếu MVP của bạn là marketplace nhỏ, CRM nội bộ, app booking, dashboard SaaS mini, cộng đồng nhỏ, blog platform, app quản lý dữ liệu… PocketBase rất phù hợp.
Khi nào nên thay Supabase bằng PocketBase?
Nên dùng PocketBase nếu
– Cần dựng MVP nhanh – Team nhỏ, 1-3 dev – Dữ liệu chưa lớn – Logic backend chưa quá phức tạp – Muốn tự host rẻ – Không muốn cấu hình nhiều – Cần admin panel ngay – Cần auth + CRUD + upload file – Traffic giai đoạn đầu chưa cao
Ví dụ MVP:
– App quản lý khách hàng – Booking lịch tư vấn – Directory sản phẩm – Mini social app – SaaS dashboard nội bộ – Công cụ quản trị content – App đăng bài, lưu ảnh, comment
Không nên dùng PocketBase nếu
– Cần scale ngang phức tạp – Cần SQL cực mạnh, analytics nặng – Cần row-level security kiểu Postgres – Nhiều service cần ghi đồng thời lớn – Cần replication, high availability chuẩn production lớn – Team đã quen Supabase/Postgres sâu
PocketBase không “thay Supabase trong mọi trường hợp”. Nó thay tốt ở vùng MVP nhẹ, tốc độ cao, chi phí thấp.
So sánh nhanh: Supabase vs PocketBase
| Tiêu chí | Supabase | PocketBase | |—|—|—| | Database | Postgres | SQLite | | Setup | Nhiều thành phần hơn | 1 binary | | Admin UI | Có dashboard cloud | Có admin UI built-in | | Auth | Mạnh, nhiều provider | Đủ dùng, dễ setup | | Realtime | Có | Có | | File storage | Có bucket | Có file field | | Deploy | Cloud/self-host phức tạp hơn | Rất nhẹ | | Scale | Tốt hơn | Giới hạn hơn | | MVP speed | Nhanh | Rất nhanh | | Learning curve | Trung bình | Thấp |
Kết luận ngắn: Supabase mạnh hơn. PocketBase nhanh hơn cho MVP nhỏ.
Kiến trúc MVP mẫu
Giả sử bạn xây app “mini marketplace”:
– User đăng ký/đăng nhập – User tạo sản phẩm – Sản phẩm có ảnh – Người khác xem danh sách sản phẩm – Chủ sở hữu sửa/xóa sản phẩm của mình
Backend cần:
– Collection users
– Collection products
– Auth
– File upload ảnh
– Rule phân quyền
– API cho frontend
PocketBase lo gần hết.
Bước 1: Cài PocketBase
Vào trang tải:
https://pocketbase.io/docs/Tải binary theo OS. Ví dụ Linux:
wget https://github.com/pocketbase/pocketbase/releases/download/v0.22.0/pocketbase_0.22.0_linux_amd64.zip
unzip pocketbase_0.22.0_linux_amd64.zip
chmod +x pocketbase
./pocketbase serveMặc định chạy tại:
http://127.0.0.1:8090Admin UI:
http://127.0.0.1:8090/_/Lần đầu mở admin UI → tạo admin account.
Xong. Backend đã chạy.
Bước 2: Tạo collection dữ liệu
Vào admin UI → Collections → New collection.
Tạo collection products.
Fields gợi ý:
– title → text, required
– description → editor hoặc text
– price → number
– image → file
– owner → relation tới users
– status → select: draft, published
PocketBase tự có collection users cho auth. Bạn không cần tự dựng bảng user từ đầu.
Sau khi lưu, PocketBase tự tạo REST API cho products.
Ví dụ endpoint:
GET /api/collections/products/records
POST /api/collections/products/records
GET /api/collections/products/records/:id
PATCH /api/collections/products/records/:id
DELETE /api/collections/products/records/:idKhông cần viết controller CRUD.
Bước 3: Thiết lập access rules
Đây là phần quan trọng. Nếu để sai, dữ liệu có thể public quá mức.
Trong collection products, cấu hình rules:
List/Search rule
Cho mọi người xem sản phẩm đã publish:
status = "published"View rule
status = "published" || owner = @request.auth.idNghĩa là: sản phẩm public ai cũng xem; sản phẩm riêng chỉ chủ xem.
Create rule
Chỉ user đã login được tạo:
@request.auth.id != ""Update rule
Chỉ owner được sửa:
owner = @request.auth.idDelete rule
Chỉ owner được xóa:
owner = @request.auth.idKhi tạo product từ frontend, set owner bằng ID user hiện tại. Có thể dùng hook để tự set owner phía server nếu muốn chặt hơn.
Bước 4: Kết nối frontend
Cài SDK JavaScript:
npm install pocketbaseTạo client:
import PocketBase from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');
export default pb;
Đăng ký user
await pb.collection('users').create({
email: '[email protected]',
password: '12345678',
passwordConfirm: '12345678',
});Đăng nhập
await pb.collection('users').authWithPassword(
'[email protected]',
'12345678'
);
console.log(pb.authStore.model);
console.log(pb.authStore.token);
SDK tự lưu auth vào localStorage. App reload vẫn giữ session.
Lấy danh sách sản phẩm
const products = await pb.collection('products').getList(1, 20, {
filter: 'status = "published"',
sort: '-created',
});
console.log(products.items);
Tạo sản phẩm có ảnh
const formData = new FormData();
formData.append('title', 'Áo thun MVP');
formData.append('description', 'Sản phẩm test');
formData.append('price', 199000);
formData.append('status', 'published');
formData.append('owner', pb.authStore.model.id);
formData.append('image', fileInput.files[0]);
const record = await pb.collection('products').create(formData);
Hiển thị ảnh
PocketBase lưu file theo record. URL ảnh:
const url = pb.files.getUrl(record, record.image);Rất tiện. Không cần cấu hình bucket như Supabase Storage.
Bước 5: Realtime trong vài dòng
PocketBase hỗ trợ realtime subscription.
Ví dụ lắng nghe product mới:
pb.collection('products').subscribe('*', function (e) {
console.log(e.action); // create, update, delete
console.log(e.record);
});Hủy subscription:
pb.collection('products').unsubscribe('*');Dùng cho:
– Dashboard live – Chat nhỏ – Notification đơn giản – Danh sách order realtime – Admin panel cập nhật tức thì
Nếu realtime phức tạp, nhiều channel, presence, broadcast lớn → cân nhắc kỹ. Nhưng cho MVP → đủ dùng.
Bước 6: Deploy nhanh lên VPS
PocketBase hợp nhất với VPS nhỏ. Ví dụ server Ubuntu 1GB RAM vẫn chạy ổn cho MVP nhẹ.
Upload binary + thư mục pb_data.
Chạy thử:
./pocketbase serve --http=0.0.0.0:8090Nên chạy qua reverse proxy như Caddy hoặc Nginx.
Ví dụ Caddyfile:
api.example.com {
reverse_proxy 127.0.0.1:8090
}Chạy PocketBase bằng systemd:
[Unit]
Description=PocketBase
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/pocketbase
ExecStart=/opt/pocketbase/pocketbase serve --http=127.0.0.1:8090
Restart=always
[Install]
WantedBy=multi-user.target
Enable:
sudo systemctl daemon-reload
sudo systemctl enable pocketbase
sudo systemctl start pocketbaseKiểm tra:
sudo systemctl status pocketbaseBackup: đừng bỏ qua
PocketBase dùng SQLite và lưu dữ liệu trong pb_data. Vì vậy backup rất đơn giản nhưng cực quan trọng.
Cần backup:
– File SQLite – Uploaded files – Config/schema
Thực tế nên backup toàn bộ:
tar -czf pb_backup_$(date +%F).tar.gz pb_dataTốt hơn: cron backup hằng ngày, sync sang S3/R2/Backblaze.
MVP chết vì mất dữ liệu → rất đau. PocketBase nhẹ không có nghĩa được bỏ backup.
Mở rộng logic backend
Mặc định CRUD đủ cho nhiều MVP. Khi cần logic thêm, PocketBase cho extend bằng:
– Go – JavaScript hooks/migrations
Ví dụ use case:
– Tự set owner
– Gửi email sau khi tạo order
– Validate dữ liệu custom
– Tạo invoice
– Tính điểm user
– Gọi API thanh toán
PocketBase không ép bạn viết backend từ đầu, nhưng vẫn cho can thiệp khi cần.
Những giới hạn cần biết trước
PocketBase rất tốt, nhưng không phải “viên đạn bạc”.
SQLite có giới hạn
SQLite nhanh, bền, đơn giản. Nhưng workload ghi đồng thời rất lớn không phải điểm mạnh. Nếu app thành công lớn, nhiều concurrent writes → có thể cần chuyển sang Postgres/Supabase/custom backend.
Scale ngang khó hơn
PocketBase thường chạy một instance chính. Muốn nhiều node, shared file storage, replication… sẽ phức tạp hơn Supabase.
Ecosystem nhỏ hơn
Supabase có ecosystem lớn: Postgres extension, Edge Functions, Auth provider, Storage policy, hosted platform. PocketBase gọn hơn, ít thành phần hơn, ít lựa chọn hơn.
Migration dài hạn cần kế hoạch
Nếu MVP có khả năng thành sản phẩm lớn, hãy thiết kế schema sạch, tránh phụ thuộc quá sâu vào đặc thù PocketBase. Khi cần migrate sang Postgres, bạn sẽ đỡ đau.
Checklist dựng backend MVP trong 30 phút
Lộ trình thực tế:
1. 0-5 phút: tải PocketBase, chạy local, tạo admin.
2. 5-10 phút: tạo collections: products, orders, profiles…
3. 10-15 phút: thêm fields, relation, file field.
4. 15-20 phút: cấu hình access rules.
5. 20-25 phút: kết nối frontend bằng SDK.
6. 25-30 phút: test auth, CRUD, upload, realtime.
Sau 30 phút, bạn có backend thật, có admin UI, có API, có auth. Không phải mock. Không phải JSON server. Không phải viết Express/Nest từ đầu.
Kết luận thực tế
Nếu bạn đang xây MVP, mục tiêu không phải kiến trúc hoàn hảo. Mục tiêu là ra sản phẩm nhanh, test nhu cầu thật, sửa nhanh.
Supabase phù hợp khi bạn cần Postgres, scale tốt hơn, ecosystem lớn hơn. PocketBase phù hợp khi bạn cần backend nhẹ, tự host dễ, setup nhanh, chi phí thấp.Công thức đề xuất:
– MVP nhỏ, cần ship tuần này → PocketBase – App có dấu hiệu scale mạnh, query phức tạp → Supabase/Postgres – Chưa chắc thị trường cần gì → PocketBase trước – Đã có traction rõ → đánh giá migrate hoặc harden backend
PocketBase không thay Supabase ở mọi dự án. Nhưng với MVP, nó có một lợi thế cực lớn: giảm ma sát. Ít config hơn. Ít tầng hơn. Ít thứ để hỏng hơn. Bạn tập trung vào sản phẩm, người dùng, vòng lặp phản hồi.
Với nhiều founder/dev indie, vậy là đủ để bắt đầu.
Bình luận (0)
Chưa có bình luận. Hãy là người đầu tiên!