Khởi Động Nhanh: Chạy PocketBase Trong 5 Phút
PocketBase được phát hành dưới dạng một file thực thi duy nhất. Tải về, chạy lên và bạn đã có một backend hoạt động đầy đủ: database, REST API, xác thực, lưu trữ file và admin dashboard — tất cả đã tích hợp sẵn. Không cần Docker, không cần Node.js, không cần cài Postgres.
Cách chạy trên Linux:
# Tải bản phát hành mới nhất (kiểm tra https://pocketbase.io/docs để biết phiên bản hiện tại)
wget https://github.com/pocketbase/pocketbase/releases/download/v0.22.0/pocketbase_0.22.0_linux_amd64.zip
# Giải nén
unzip pocketbase_0.22.0_linux_amd64.zip
# Cấp quyền thực thi và chạy
chmod +x pocketbase
./pocketbase serve
Bạn sẽ thấy output như sau:
2024/01/15 10:00:00 Server started at http://127.0.0.1:8090
- REST API: http://127.0.0.1:8090/api/
- Admin UI: http://127.0.0.1:8090/_/
Mở http://127.0.0.1:8090/_/ trên trình duyệt. Tạo tài khoản admin khi được yêu cầu là bạn đã vào được dashboard.
macOS cũng làm tương tự — chỉ cần tải bản darwin. Trên Windows, tải file zip dành cho Windows và chạy pocketbase.exe serve từ Command Prompt.
Tạo Collection Đầu Tiên
Hãy coi collection như một bảng trong database. Trong admin dashboard, click New collection, đặt tên là posts và thêm các field sau:
- title — Text, bắt buộc
- content — Editor (rich text)
- published — Bool
- author — Relation (liên kết tới collection
users)
Lưu lại. PocketBase tự động tạo REST API cho collection mới. Bây giờ bạn đã có endpoint /api/collections/posts/records hoạt động — không cần viết một dòng code nào.
Tìm Hiểu Sâu: Làm Việc với API
REST API tuân theo các quy ước bạn đã quen thuộc. Mỗi collection đều có cùng một bộ endpoints, và bạn có thể lọc, sắp xếp, phân trang bằng URL parameters.
Lấy Records
# Lấy tất cả bài viết
curl http://127.0.0.1:8090/api/collections/posts/records
# Lọc và sắp xếp
curl "http://127.0.0.1:8090/api/collections/posts/records?filter=(published=true)&sort=-created&perPage=10"
# Lấy một record theo ID
curl http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID
Tạo và Cập Nhật Records
# Tạo bài viết mới (cần auth token nếu collection rules yêu cầu)
curl -X POST http://127.0.0.1:8090/api/collections/posts/records \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"title": "Bài Viết Đầu Tiên", "content": "Xin chào thế giới", "published": true}'
# Cập nhật một record
curl -X PATCH http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{"published": false}'
Xác Thực
Quản lý người dùng đã được tích hợp sẵn. Collection users có ngay từ đầu — bạn không cần tạo. Đăng ký và đăng nhập trông như thế này:
# Đăng ký người dùng mới
curl -X POST http://127.0.0.1:8090/api/collections/users/records \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "password123", "passwordConfirm": "password123"}'
# Đăng nhập và lấy token
curl -X POST http://127.0.0.1:8090/api/collections/users/auth-with-password \
-H "Content-Type: application/json" \
-d '{"identity": "[email protected]", "password": "password123"}'
Response khi đăng nhập bao gồm field token. Dùng nó dưới dạng Authorization: Bearer TOKEN trong các request tiếp theo.
Sử Dụng JavaScript SDK
Với frontend, SDK JS chính thức gọn gàng hơn nhiều so với raw fetch calls:
npm install pocketbase
import PocketBase from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');
// Đăng nhập
const authData = await pb.collection('users').authWithPassword('[email protected]', 'password123');
// Lấy danh sách bài viết
const posts = await pb.collection('posts').getList(1, 20, {
filter: 'published = true',
sort: '-created',
});
// Tạo bài viết
const newPost = await pb.collection('posts').create({
title: 'Xin chào từ SDK',
content: 'Đây là bài viết của tôi',
published: true,
});
Nâng Cao: Real-Time Subscriptions và Upload File
Cập Nhật Real-Time với Subscribe
Cập nhật live là điểm mạnh nhất của PocketBase. Subscribe vào một collection và các thay đổi sẽ được gửi tới client ngay tức thì — không cần polling, không cần xử lý refresh thủ công:
// Đăng ký nhận tất cả thay đổi trong collection 'posts'
await pb.collection('posts').subscribe('*', function(e) {
console.log('Hành động:', e.action); // 'create', 'update', hoặc 'delete'
console.log('Bản ghi:', e.record);
});
// Đăng ký nhận thay đổi của một record cụ thể
await pb.collection('posts').subscribe('RECORD_ID', function(e) {
console.log('Bài viết này đã thay đổi:', e.record);
});
// Hủy đăng ký khi xong (ví dụ: khi component unmounts)
pb.collection('posts').unsubscribe('*');
PocketBase dùng Server-Sent Events (SSE) bên dưới, không phải WebSockets. Điều này có nghĩa là nó hoạt động qua hầu hết các firewall và proxy mà không cần cấu hình đặc biệt.
Upload File
Thêm field File vào collection trong admin dashboard, sau đó upload file qua API:
const formData = new FormData();
formData.append('title', 'Bài viết có đính kèm');
formData.append('attachment', fileInput.files[0]);
const record = await pb.collection('posts').create(formData);
// Lấy URL của file
const fileUrl = pb.files.getUrl(record, record.attachment);
Collection Rules và Kiểm Soát Truy Cập
Mỗi collection có API Rules cho read, create, update và delete. Chúng dùng cú pháp filter của PocketBase — cú pháp tương tự khi bạn query records:
- Để trống → mọi người đều truy cập được (phù hợp cho public read)
@request.auth.id != ""→ chỉ người dùng đã xác thựcauthor = @request.auth.id→ chỉ tác giả của record@request.auth.id = @collection.admins.id→ chỉ admin
Thiết lập blog thông thường: List/View rules để trống để bài viết public. Create yêu cầu xác thực. Update/Delete yêu cầu author = @request.auth.id.
Mở Rộng với Go Hooks
Cần logic server-side tùy chỉnh? Nhúng PocketBase vào ứng dụng Go và gắn hooks:
go mod init myapp
go get github.com/pocketbase/pocketbase
package main
import (
"log"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
)
func main() {
app := pocketbase.New()
// Gửi email sau khi một bài viết được tạo
app.OnRecordAfterCreateRequest("posts").Add(func(e *core.RecordCreateEvent) error {
log.Println("Bài viết mới được tạo:", e.Record.GetString("title"))
// gửi email, trigger webhook, v.v.
return nil
})
if err := app.Start(); err != nil {
log.Fatal(err)
}
}
Mẹo Thực Tế Khi Triển Khai
Chạy PocketBase trên Production
Trên VPS, hãy bọc PocketBase trong một systemd service để nó tự khởi động khi boot và tự restart sau khi crash:
# /etc/systemd/system/pocketbase.service
[Unit]
Description=Dịch vụ PocketBase
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/pocketbase
ExecStart=/opt/pocketbase/pocketbase serve --http=0.0.0.0:8090
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable pocketbase
sudo systemctl start pocketbase
Đặt Nginx ở phía trước để xử lý HTTPS. Một chi tiết ít người biết: hãy tắt proxy buffering, nếu không các kết nối SSE sẽ bị treo âm thầm:
location / {
proxy_pass http://127.0.0.1:8090;
proxy_set_header Host $host;
# Quan trọng cho SSE (real-time subscriptions)
proxy_buffering off;
proxy_read_timeout 3600;
}
Chiến Lược Backup
Toàn bộ dữ liệu — records, users, settings — nằm trong một file SQLite duy nhất tại pb_data/data.db. Backup chỉ đơn giản là copy một file:
# Backup hàng ngày đơn giản
0 2 * * * cp /opt/pocketbase/pb_data/data.db /backups/pocketbase-$(date +%Y%m%d).db
Bạn cũng có thể kích hoạt backup qua admin API mà không cần dừng server.
Quy Trình Import Dữ Liệu
Khi migrate dữ liệu hiện có vào PocketBase, tôi thường cần convert CSV export từ các hệ thống cũ sang JSON trước khi import. Công cụ tôi hay dùng là toolcraft.app/vi/tools/data/csv-to-json — chạy hoàn toàn trên trình duyệt nên dữ liệu không bao giờ rời khỏi máy bạn, điều này đặc biệt quan trọng khi CSV chứa thông tin người dùng hoặc dữ liệu nhạy cảm. Sau khi có JSON, một script nhỏ sẽ xử lý việc bulk insert qua API của PocketBase.
Khi Nào Nên Dùng PocketBase (và Khi Nào Không)
PocketBase phù hợp khi:
- Bạn đang xây dựng side project hoặc MVP và muốn có backend chạy được trong một giờ
- Một server là đủ — công cụ nội bộ, admin dashboard, ứng dụng mobile nhỏ
- Bạn cần offline-sync trong mobile app mà không muốn tự mình xử lý sự phức tạp đó
- Bạn đang prototype và chưa muốn cam kết với một full stack cụ thể
Điểm hạn chế:
- Ứng dụng cần horizontal scaling trên nhiều server — SQLite không hỗ trợ distributed writes
- Workload write cao: SQLite xử lý concurrent reads tốt nhưng bắt đầu gặp khó khăn khi vượt vài trăm writes/giây dưới tranh chấp tài nguyên
- Nhóm cần các SQL query phức tạp, stored procedures, hoặc ràng buộc chặt chẽ ở cấp database
Với các dự án giai đoạn đầu, một file binary ~30MB đã bao gồm database, API, xác thực và lưu trữ file giúp thay thế bốn dịch vụ riêng biệt mà bạn đáng lẽ phải dựng lên và duy trì. Đó là sự đánh đổi thực sự xứng đáng.

