UI sai thì sửa được. Copy sai thì sửa được. Database sai thì đau hơn nhiều. Một cột bị xóa, một migration chạy nhầm production, một auth policy mở quá rộng, một seed script ghi đè data thật. Đây là loại lỗi vibe coding rất dễ tạo ra nếu bạn để agent “làm luôn backend cho tiện”.

Nguyên tắc của bài này đơn giản: schema không phải chỗ để đoán.

Mock data khác database thật

Trong prototype, sample data là tốt. Nó giúp bạn thấy UI và flow. Nhưng sample data sống trong code khác hoàn toàn data thật trong database.

Khi agent đề xuất “thêm database”, hỏi ngay:

  • database nào?
  • bảng nào?
  • cột nào?
  • auth policy nào?
  • migration file ở đâu?
  • seed data là fake hay copy từ production?
  • preview có database riêng không?

Nếu agent trả lời chung chung kiểu “I will set up a database”, chưa approve.

Branch database trước khi đổi schema

Supabase Branching là một ví dụ tốt về mental model đúng: branch tạo môi trường riêng để test schema, config, migration, Edge Functions mà không chạm production. Docs hiện tại nói mỗi branch là một environment riêng, có API credentials riêng; preview branches phù hợp cho testing ngắn hạn và không bắt đầu với production data mặc định.

Bạn không cần dùng Supabase mới áp dụng được nguyên tắc này. Với bất kỳ database nào, hãy tách:

  • production database;
  • staging/preview database;
  • local/dev database;
  • seed data không nhạy cảm.

Preview frontend mà gọi production database thì chưa phải preview an toàn.

Migration phải là file review được

Thay đổi schema nên đi qua migration file hoặc diff review được. Không nên để agent click dashboard lung tung rồi bạn không biết đã đổi gì.

Prompt tốt:

Propose database changes first.
Do not apply them yet.
Output:
- table changes
- columns added/removed
- indexes
- policies
- migration file name
- rollback risk
- seed data needed

Nếu migration xóa cột hoặc đổi type, coi là high-risk. Nếu migration thêm cột nullable, risk thấp hơn. Nếu migration đổi auth/RLS policy, cần review kỹ hơn cả UI.

Seed data không được là production dump

Preview cần data để test. Nhưng data đó nên là seed giả hoặc đã ẩn danh. Supabase docs nói branch mới không bắt đầu với data từ main project để bảo vệ dữ liệu nhạy cảm; nếu cần data, dùng seed file khi workflow hỗ trợ.

Seed tốt:

  • tên giả;
  • email domain test;
  • số điện thoại giả;
  • vài case edge rõ ràng;
  • không có customer thật.

Seed tệ:

  • export production CSV;
  • order/customer thật;
  • token/API key;
  • file upload thật;
  • data y tế/tài chính.

Non-tech user thường muốn “giống thật” để demo. Hãy làm data giống cấu trúc thật, không phải copy data thật.

Auth policy là một phần của schema

Database không chỉ có table. Với Supabase/Firebase hoặc backend hiện đại, rule/policy quyết định ai đọc/ghi gì. Vibe coding rất dễ tạo bug kiểu:

  • user A thấy data của user B;
  • anonymous user ghi được record;
  • admin-only field hiện ra client;
  • preview policy khác production policy.

Trước khi ship, yêu cầu agent viết policy bằng ngôn ngữ người:

Explain database access rules in plain Vietnamese:
- who can read bookings
- who can create bookings
- who can edit status
- who can delete
- what anonymous users can do

Nếu giải thích này nghe sai, policy cũng có thể sai.

Rollback database không giống rollback UI

Frontend rollback thường dễ: trỏ lại deployment cũ. Database rollback khó hơn vì data đã đổi. Nếu migration thêm cột, rollback có thể đơn giản. Nếu migration xóa cột hoặc transform data, rollback cần backup hoặc migration ngược.

Trước migration, hỏi:

  • Có backup không?
  • Migration có destructive không?
  • Có down migration không?
  • Có chạy thử trên preview chưa?
  • Có data thật bị transform không?
  • Nếu fail giữa chừng thì trạng thái database ra sao?

Với non-tech, default nên là: không approve destructive migration từ agent nếu chưa có developer review.

Chốt lại

Database là nơi vibe coding phải chậm lại. UI có thể thử nhanh, database thì cần branch, migration, seed data, policy, backup và rollback. Nếu chưa có các thứ đó, hãy giữ app ở mức prototype với sample data.

Agent có thể giúp viết migration, nhưng bạn phải bắt nó giải thích schema và risk trước khi chạy. Schema không phải chỗ để “cứ thử xem”.

Tham khảo