Cú điện thoại lúc 2 giờ sáng và giới hạn của Database truyền thống
Đúng 2 giờ sáng, điện thoại mình rung bần bật. Hệ thống báo lỗi 504 Gateway Timeout hàng loạt. Kiểm tra log trên Vercel, mình thấy một hàng dài lỗi ETIMEDOUT. Vấn đề không nằm ở logic code. Con PostgreSQL instance đặt tại Singapore đang “khóc thét” vì không gánh nổi lượng connection tăng đột biến từ các Edge Runtime phân tán khắp toàn cầu.
Lúc đó mình mới thấm thía cái giá của việc dùng Database tập trung cho hệ thống Serverless. Mỗi khi Lambda function khởi tạo (Cold Start), nó phải hì hục thiết lập kết nối TCP mới. Cộng thêm mớ overhead từ SSL/TLS, latency (độ trễ) tăng vọt lên mức không thể chấp nhận được. Mình đã thử nâng cấp Connection Pool, nhưng hóa đơn AWS vọt lên thêm hơn $50/tháng mà hiệu năng vẫn lẹt đẹt. Đó là lúc mình tìm đến Turso và LibSQL.
Ba “hố vôi” phổ biến khi chọn Database cho Serverless
Trước khi chốt phương án, mình đã từng thử qua 3 cách tiếp cận này. Mỗi cái đều có những nhược điểm chí mạng trong môi trường Edge:
1. SQL truyền thống (PostgreSQL/MySQL)
- Vấn đề: Connection limit là một cực hình. Bạn buộc phải tốn thêm tiền cho PgBouncer hoặc AWS RDS Proxy để quản lý kết nối. Nếu user ở Mỹ mà DB ở Singapore, latency 300ms là chuyện bình thường.
2. NoSQL (DynamoDB/MongoDB Atlas)
- Vấn đề: Bạn phải học lại cách modeling dữ liệu. Query phức tạp hoặc JOIN là một thử thách thực sự. Mình từng mất trắng 3 ngày chỉ để viết lại đống logic query vốn chỉ tốn 5 phút với SQL truyền thống.
3. SQLite tại local
- Vấn đề: Nhanh nhưng không thể chia sẻ dữ liệu. Serverless là stateless. Mỗi lần function chạy, nó lại tạo ra một file SQLite trống rỗng, khiến dữ liệu cũ biến mất hoàn toàn.
Turso xuất hiện như một mảnh ghép hoàn hảo: Nó mang sức mạnh của SQLite lên Cloud. Turso hỗ trợ replication ra hàng chục location toàn cầu và dùng giao thức HTTP thay vì TCP để loại bỏ hoàn toàn nỗi lo nghẽn kết nối.
Tại sao Turso và LibSQL lại đáng đồng tiền bát gạo?
LibSQL là bản fork mã nguồn mở của SQLite do đội ngũ Turso tối ưu hóa. Sau khi benchmark thực tế, đây là 3 lý do mình quyết định chuyển toàn bộ dự án sang Turso:
- Phản hồi siêu tốc: Turso cho phép tạo bản sao (replicas) ở gần người dùng nhất. User ở London sẽ truy vấn ngay tại London thay vì phải đợi tín hiệu bay nửa vòng trái đất.
- Giao thức HTTP/WebSockets: LibSQL client không duy trì kết nối TCP nặng nề. Điều này cực kỳ phù hợp với các function chỉ sống trong vài giây trên Vercel hay Cloudflare Workers.
- Trải nghiệm Developer: CLI của Turso cực mượt. Mình chỉ mất chưa đầy 30 giây để khởi tạo một database sẵn sàng cho production.
Hướng dẫn triển khai Turso cho dự án Node.js
Dưới đây là các bước để bạn setup một database Turso và kết nối với ứng dụng TypeScript.
Bước 1: Khởi tạo Database qua CLI
Đầu tiên, hãy cài đặt CLI. Nếu dùng macOS, bạn dùng Brew cho nhanh:
brew install tursodatabase/tap/turso
turso auth signup
turso db create my-awesome-app
Lệnh này sẽ trả về một URL có dạng libsql://my-awesome-app-user.turso.io. Hãy lưu nó lại.
Bước 2: Bảo mật với Auth Token
Đừng bao giờ để database mở toang cho thiên hạ. Bạn cần tạo một token truy cập:
turso db tokens create my-awesome-app
Bước 3: Kết nối từ Code
Cài đặt driver chính thức từ LibSQL:
npm install @libsql/client dotenv
Dưới đây là cách mình thường viết script để tương tác với dữ liệu. Cú pháp cực kỳ quen thuộc nếu bạn đã từng dùng SQLite:
import { createClient } from "@libsql/client";
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
async function initUser() {
// Thao tác với DB
await client.execute(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
)
`);
await client.execute({
sql: "INSERT INTO users (name) VALUES (?)",
args: ["DevPro"],
});
const rs = await client.execute("SELECT * FROM users");
console.table(rs.rows);
}
Kinh nghiệm thực tế: Khi nào Turso không phải là lựa chọn tốt?
Turso rất mạnh nhưng không phải là “vạn năng”. Qua một thời gian chạy production, mình rút ra hai điểm cần lưu ý.
Thứ nhất, SQLite thiếu các kiểu dữ liệu nâng cao như JSONB của PostgreSQL. Nếu app của bạn phụ thuộc nặng vào PostGIS hoặc query JSON phức tạp, việc chuyển sang Turso sẽ khiến code ở tầng application trở nên cồng kềnh hơn.
Thứ hai là cơ chế Single-Primary. Mọi thao tác GHI vẫn phải gửi về region chính. Nếu ứng dụng của bạn có tần suất GHI liên tục từ khắp nơi, độ trễ cho lệnh Write vẫn sẽ tồn tại. Turso thực sự tỏa sáng nhất với các app Read-heavy (đọc nhiều, ghi ít).
Tuyệt chiêu tối ưu: Embedded Replicas
Đây là tính năng mình thích nhất. Bạn có thể đồng bộ một bản sao DB ngay vào ổ cứng của server chạy app. Khi đó, các câu lệnh SELECT sẽ chạy với tốc độ local (gần như 0ms latency). Driver sẽ tự động đồng bộ dữ liệu ngầm cho bạn.
const client = createClient({
url: "file:local.db",
syncUrl: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
// Sync dữ liệu từ Cloud về local
await client.sync();
Lời kết
Chọn Database cho Serverless hiện nay không chỉ là chọn giữa SQL hay NoSQL. Quan trọng nhất là Data Proximity – đưa dữ liệu đến càng gần người dùng càng tốt. Turso và LibSQL đã làm rất tốt việc này mà vẫn giữ được sự đơn giản của SQL. Nếu bạn mệt mỏi với việc config cụm DB cồng kềnh, hãy thử Turso để thấy sự khác biệt về hiệu năng ngay lập tức.

