skip to content
Thai Le

ERD vẽ tay là nợ kỹ thuật trá hình

ERD vẽ tay trông đẹp lúc đầu, nhưng lệch khỏi schema thật sau mỗi migration. Để schema tự sinh tài liệu là cách thực tế hơn — docs sống cùng code, không chết dần.

Ngày đăng
Sửa lần cuối
Độ dài
7 phút đọc
ERD vẽ tay lệch khỏi schema thật — minh hoạ tài liệu database sinh tự động từ code
Table of Contents

Hi friend! 👋

Lần đầu mở một codebase lạ, mình được “onboard” bằng một file PNG: ERD của database. Hộp ngay ngắn, mũi tên thẳng tắp, màu sắc đồng bộ. Mình dùng nó làm bản đồ suốt hai tuần.

Rồi một hôm trace quan hệ từ orders sang payments — phát hiện mũi tên ấy trỏ tới một cột đã không tồn tại từ bốn migration trước. Bản đồ đẹp đấy. Chỉ là vẽ sai đường từ lâu rồi.

📖 Nói nhanh cho bạn chưa quen:

ERD giống bản đồ gia phả của database: bảng nào nối bảng nào, quan hệ cha-con ra sao. Còn schema — cấu trúc thật của database (bảng, cột, khoá, ràng buộc) — chính là sự thật. Vẽ ERD bằng tay giống viết gia phả bằng tay: đúng lúc viết, nhưng mỗi lần schema đổi mà sơ đồ không cập nhật, cuốn gia phả dần thành tiểu thuyết.

Tài liệu chết vì đứng ngoài quy trình

Một tài liệu database thường chết theo ba bước rất quen thuộc:

  • Ban đầu, ai đó vẽ ERD trong Miro, Draw.io, Excel, Notion hoặc một file PNG rất đẹp.
  • Sau đó, team thay đổi schema qua migration, ORM hoặc SQL script.
  • Cuối cùng, không ai cập nhật sơ đồ vì việc đó không nằm trong flow review, không có test fail, không có CI nhắc, cũng không ảnh hưởng trực tiếp đến deploy.

Và thế là tài liệu bắt đầu nói dối.

Sơ đồ tài liệu vẽ tay lệch dần khỏi schema thật theo thời gian

Tài liệu thủ công không hỏng ngay. Nó hỏng từ từ, nên team thường phát hiện quá muộn.

Điều nguy hiểm không phải thiếu tài liệu. Thiếu thì ai cũng cảnh giác. Điều nguy hiểm là có một tài liệu trông đáng tin nhưng đã lệch khỏi hệ thống thật. Nó khiến người mới hiểu sai quan hệ bảng. Nó khiến BA và dev tranh luận trên một hình ảnh cũ. Nó khiến reviewer bỏ sót một foreign key quan trọng vì sơ đồ đẹp quá — chỉ là không còn đúng nữa.

Nếu một tài liệu không được sinh ra từ source of truth, nó sẽ phải cạnh tranh với source of truth. Và nó sẽ thua.

Đừng chăm viết docs hơn — hãy giảm quyền nói dối của docs

Phản xạ phổ biến khi docs lệch schema là kêu gọi kỷ luật: “Từ nay nhớ cập nhật tài liệu sau khi sửa database.”

Nghe thì đúng. Nhưng trong phần mềm, “nhớ làm” là một cơ chế yếu. Mình đã thấy cái vòng này lặp lại ở nhiều nơi: vẽ tay rồi lệch, kêu “nhớ cập nhật” rồi chẳng ai nhớ — và nó cứ kéo dài âm thầm cho tới lúc một người mới hiểu sai quan hệ bảng. Những thứ quan trọng không nên phụ thuộc vào trí nhớ và thiện chí. Chúng nên nằm trong pipeline.

Mình thích cách nghĩ này hơn:

Nếu schema đổi, tài liệu phải đổi. Nếu tài liệu không đổi, CI nên làm team khó chịu.

Nghĩa là đảo lại vai trò: sơ đồ không còn là một artifact thủ công đứng bên cạnh code. Sơ đồ trở thành output của code — schema-driven.


🔧 Bắt đầu setup

Liam ERD là công cụ, nhưng ý tưởng mới là phần quan trọng

Liam ERD không chỉ hấp dẫn vì nó render ERD đẹp. Phần đáng giá hơn là nó đối xử với database schema như đầu vào, rồi sinh ra một giao diện có thể tìm kiếm, zoom, filter và highlight quan hệ.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
00K00KMIT

Với public repo, mình mở schema trực tiếp qua URL dạng liambx.com/erd/p/.... Với private repo hoặc CI/CD, mình dùng CLI build ERD thành static site.

Terminal window
npx @liam-hq/cli erd build --input ./path/to/schema.sql --format postgres

Câu lệnh trên không quan trọng bằng việc: từ đây trở đi, sơ đồ có thể được sinh lại bất cứ khi nào schema đổi. Không cần mở tool, không cần kéo thả, không cần export PNG, cũng không cần hy vọng ai đó nhớ cập nhật nữa.

PNG không đủ cho database lớn

Một bức ảnh ERD tĩnh có thể ổn với 12 bảng. Nhưng khi hệ thống lên 80, 100, 150 bảng, ảnh tĩnh bắt đầu phản bội người đọc.

Kích thước chưa phải vấn đề chính. Vấn đề là khả năng đặt câu hỏi.

  • Bảng orders liên quan trực tiếp đến những bảng nào?
  • Quan hệ giữa users, roles, permissions đi qua bảng trung gian nào?
  • Có bảng nào trở thành “God table” vì quá nhiều bảng phụ thuộc vào nó không?
  • Migration mới vừa thêm quan hệ nào vào vùng billing?

Ảnh tĩnh không trả lời tốt các câu hỏi đó. Một ERD tương tác thì có cơ hội.

Search, filter, zoom, highlight không phải “nice to have”. Với database lớn, chúng là điều kiện để sơ đồ còn hữu ích.

CI mới là nơi tài liệu nên sống

Một command chạy local chỉ là demo. Quy trình thật phải nằm trong CI.

Ví dụ với tbls, mình sinh schema.json từ database, rồi để Liam ERD build giao diện tương tác từ file đó. Phần YAML cụ thể mình để ở sample repo cuối bài, không nhồi vào đây. Điều quan trọng là bức tranh lớn:

Sơ đồ pipeline schema-driven documentation từ migration đến docs tương tác

Code tạo schema. Schema tạo docs. Docs quay lại phục vụ review, onboarding và vận hành.

Với team khác, output có thể được publish lên GitHub Pages, Cloudflare Pages, S3 hoặc attach link preview vào pull request. Cách triển khai có thể đổi. Nguyên tắc không nên đổi: schema thay đổi thì tài liệu phải được máy sinh lại.


🎯 Bài này hữu ích nếu bạn:

Bạn là…Áp dụng để…
Dev mới onboardingHiểu flow nghiệp vụ mà không phải đọc 40 migration
Reviewer / Tech leadKiểm tra foreign key trên schema thật, không phải ảnh cũ
BAThấy dữ liệu nghiệp vụ chia ở đâu, nối ở đâu — không cần biết SQL
Ai chạy AI agentCung cấp schema thật làm context đáng tin cho LLM

Vì tài liệu database, nói cho cùng, là giao diện giao tiếp — không phải bản vẽ kỹ thuật.

Sơ đồ ERD tự động làm shared context cho developer, BA, reviewer, onboarding, tech lead và AI agent

Một schema thật, nhiều đối tượng cùng đọc được theo nhu cầu của họ.

Giữa dev với dev, nó giảm thời gian đoán. Giữa dev với BA, nó tạo ra một hình ảnh chung. Giữa dev với AI, nó còn quan trọng hơn.

LLM không thiếu khả năng viết code. Nó thiếu context đáng tin. Nếu mình chỉ prompt “viết API tạo order”, AI sẽ đoán. Nếu mình đưa vào schema thật, constraints thật, quan hệ thật, nullable fields thật — nó có cơ hội viết code gần hệ thống của mình hơn.

Đó là lý do output như schema.json, markdown docs từ tbls, hoặc ERD sinh từ Liam không chỉ phục vụ con người. Chúng là nguồn context tốt cho AI agent: audit schema, phát hiện thiếu index, giải thích quan hệ bảng, gợi ý refactor query.

Một tài liệu tốt trong thời AI không chỉ để đọc. Nó phải có thể được máy tiêu thụ.

Checklist áp dụng ngay:

  • Lấy schema của một dự án đang có, quăng vào Liam ERD (5 phút)
  • Thêm bước sinh schema.json vào CI mỗi khi merge migration
  • Publish ERD tương tác lên GitHub Pages / Cloudflare Pages
  • Attach link preview ERD vào template pull request
  • Bỏ hẳn ERD vẽ tay khỏi quy trình review

💡 Đúc kết:

Schema đổi, tài liệu phải đổi. Tài liệu không đổi, CI nên làm team khó chịu.


Nếu bạn muốn xem stack này hoạt động trong một project Laravel thực tế, tham khảo sample repo này:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
00K00KMIT

Hi friend! Câu hỏi đúng không phải “Ai sẽ cập nhật ERD sau sprint này?” — mà là “Vì sao ERD không tự cập nhật khi schema đổi?”. Nếu bạn cũng đang duyệt tài liệu thủ công, hoặc có cách giữ database docs sống gọn hơn — chia sẻ với mình nhé. Mình luôn muốn học thêm từ kinh nghiệm của bạn.

Mở terminal, lấy schema của dự án hiện tại, quăng vào Liam ERD. Nếu sơ đồ khiến bạn thấy hệ thống rối hơn bạn tưởng, đó không phải lỗi của công cụ. Đó là lần đầu tiên hệ thống đang nói thật với bạn.

Hẹn gặp lại ở bài sau! 👋