Database "đúng." Nhưng cũng chậm gấp 296 lần.
Tôi phát hiện database Postgres có 89 foreign key nhưng zero index — biến query millisecond thành ác mộng 843ms và suýt giết alpha launch.
Ngày 25 tháng 10, 2025. Ứng dụng SaaS cuối cùng feature-complete. Chín tính năng chính, kiến trúc multi-tenant, progressive learning — mọi thứ hoạt động. Nhưng chậm. Rất chậm.
Dashboard query bò. List nên load tức thì mất nhiều giây. Alpha tester bắt đầu hỏi "Site hỏng rồi à?"
Tôi dành hai ngày tối ưu query, viết lại RLS policies, thêm caching. Không gì có tác dụng. Rồi tôi chạy một query chẩn đoán khiến bụng tôi chìm.
89 foreign key. Zero index.
Phát hiện: Foreign Key KHÔNG tự động tạo Index
Đây là điều tôi học hôm đó, theo cách khó:
Postgres tự động tạo index cho PRIMARY KEY và UNIQUE constraints.
Postgres KHÔNG tự động tạo index cho foreign key.
Khi bạn viết org_id UUID REFERENCES organizations(id), Postgres tạo foreign key constraint (referential integrity), nhưng không tạo index trên org_id.
Query chẩn đoán:
SELECT c.conrelid::regclass AS table_name, a.attname AS column_name
FROM pg_constraint c
JOIN pg_attribute a ON a.attnum = ANY(c.conkey) AND a.attrelid = c.conrelid
WHERE c.contype = 'f'
AND NOT EXISTS (
SELECT 1 FROM pg_index i
WHERE i.indrelid = c.conrelid AND a.attnum = ANY(i.indkey)
);
89 dòng. 89 foreign key trên 32 bảng. Zero index. Mọi join, filter, RLS policy check đều full table scan.
Fix: Ngày tận thế Index
Một migration. 89 index. Thời gian migration: 4 phút.
Kết quả: Từ thảm họa đến sẵn sàng launch
Trước: Seq Scan — Execution Time: 843.271 ms
Sau: Index Scan — Execution Time: 2.847 ms
843ms → 2.8ms. Nhanh gấp 296 lần.
Dashboard load: 2-3 giây → 120ms Resource lists: 1+ giây → 45ms Cải thiện trung bình: 20-40 lần nhanh hơn
Tại sao điều này quan trọng cho Multi-Tenant SaaS
RLS policies chạy trên mọi query đơn lẻ. Không có index trên org_id, policy này buộc sequential scan mọi query.
Bài học kinh doanh: Tính năng bảo mật không tối ưu hiệu suất thực ra không an toàn — vì user sẽ rời đi trước khi trải nghiệm bảo mật.
Checklist cho bạn
Cho mọi bảng mới:
- Index foreign key columns — mọi cái
- Index cột trong RLS policies
- Index cột trong WHERE clauses thường dùng
- Cân nhắc multi-column index cho pattern query phổ biến
- Đừng over-index — mỗi index tốn storage và write performance
Suy nghĩ cuối
89 index thiếu. 2 tuần debug. Một query chẩn đoán tìm tất cả. 4 phút để sửa.
Nghịch lý? Postgres cho bạn tất cả công cụ chẩn đoán. Tôi chỉ không biết phải tìm. Giờ mọi bảng tôi tạo đều được index ngay — foreign keys, RLS columns, sort fields, mọi thứ.
Cho founder: Hiệu suất không chỉ vấn đề kỹ thuật. Đó là vấn đề chuyển đổi, giữ chân, và uy tín. Database "đúng kỹ thuật" quá chậm để dùng? Nó đang tốn khách hàng.
Cho kỹ sư: Postgres không tự động index foreign key. Nhưng bạn nên. User (và CPU database) sẽ cảm ơn bạn.
Bạn đã bao giờ có khoảnh khắc "đúng kỹ thuật nhưng chậm đau đớn" với database? Fix là gì — và mất bao lâu để tìm?
Thân mến, Chandler
Series kiến trúc STRAŦUM: Cuộc khủng hoảng hiệu suất này là mảnh cuối của puzzle multi-tenancy bắt đầu với xây multi-tenancy ngày 2, tiếp với xây lại schema hoàn toàn ngày 67, và sửa 31 màn hình trắng.





