API Pagination: Vì sao danh sách đơn hàng/giao dịch không nên load tất cả một lần?
Một lỗi rất hay gặp khi BA mới viết requirement:
“Hệ thống hiển thị toàn bộ danh sách đơn hàng/giao dịch của user.”
Nghe có vẻ bình thường.
Nhưng mấy anh Dev sẽ hỏi ngay:
“Toàn bộ là bao nhiêu bản ghi?”
“1 tháng, 1 năm hay 5 năm?”
“Load một lần hay phân trang?”
“Nếu đang load thì dữ liệu mới phát sinh sao?”
-> Đây là lúc mấy ní BA cần hiểu một khái niệm rất quan trọng trong API:
Pagination – phân trang dữ liệu.
1️⃣ Pagination là gì?
Pagination là cách hệ thống chia danh sách dữ liệu lớn thành nhiều phần nhỏ để trả về từng lần.
Thay vì load 10.000 giao dịch một lần, hệ thống chỉ load:
20 giao dịch đầu tiên
→ user kéo tiếp
→ load thêm 20 giao dịch tiếp theo
→ tiếp tục...
Ví dụ API:
GET /transactions?page=1&pageSize=20
Nghĩa là:
Lấy trang số 1
Mỗi trang 20 bản ghi
2️⃣ Vì sao không nên load tất cả một lần?
Hãy tưởng tượng user mở lịch sử giao dịch 1 năm.
Một user có thể có:
500 giao dịch
2.000 giao dịch
10.000 giao dịch
Nếu app load tất cả một lần:
API phản hồi chậm
App dễ lag
Database bị tải nặng
User phải chờ lâu
Dễ timeout
Trải nghiệm rất tệ
Với BA, đây không chỉ là vấn đề kỹ thuật.
Đây là Non-functional Requirement về performance và usability.
3️⃣ Page size và page number là gì?
Cách phổ biến nhất là dùng page number.
Ví dụ:
GET /orders?page=1&pageSize=20
GET /orders?page=2&pageSize=20
GET /orders?page=3&pageSize=20
Trong đó:
page: số trangpageSize: số bản ghi mỗi lần load
Ví dụ requirement:
Hệ thống hiển thị 20 giao dịch gần nhất trong lần load đầu tiên.
Khi user chọn “Load more”, hệ thống tải thêm 20 giao dịch tiếp theo.
Cách này dễ hiểu, dễ test, phù hợp với nhiều danh sách đơn giản.
4️⃣ Cursor pagination là gì?
Ngoài page number, nhiều hệ thống dùng cursor.
Ví dụ:
GET /transactions?limit=20&cursor=abc123
Cursor có thể hiểu đơn giản là:
“Lấy tiếp dữ liệu sau vị trí này.”
Cách này hữu ích khi dữ liệu thay đổi liên tục, ví dụ:
Lịch sử giao dịch ngân hàng
Danh sách notification
Danh sách đơn hàng realtime
Vì nếu dùng page number, dữ liệu mới phát sinh có thể làm lệch trang.
5️⃣ Case thực tế: User kéo danh sách giao dịch 1 năm
Yêu cầu mơ hồ:
“User có thể xem lịch sử giao dịch 1 năm.”
BA không nên chỉ viết như vậy.
BA cần làm rõ:
Lần đầu load bao nhiêu bản ghi?
Sort theo thời gian nào?
User kéo xuống thì load tiếp hay bấm “Load more”?
Có filter theo ngày không?
Có giới hạn khoảng thời gian truy vấn không?
Nếu có giao dịch mới phát sinh trong lúc user đang xem thì có bị trùng/mất bản ghi không?
Ví dụ flow hợp lý:
User mở Transaction History
→ System load 20 giao dịch mới nhất
→ User kéo xuống
→ System load tiếp 20 giao dịch cũ hơn
→ User lọc theo khoảng thời gian nếu cần
6️⃣ BA cần viết requirement gì?
Thay vì viết:
“Hiển thị danh sách giao dịch.”
Hãy viết rõ hơn:
Functional Requirement
Hệ thống hiển thị danh sách giao dịch theo thứ tự mới nhất trước.
Lần đầu tải tối đa 20 bản ghi.
User có thể tải thêm bằng nút “Load more” hoặc thao tác scroll.
Mỗi lần tải thêm tối đa 20 bản ghi.
Khi không còn dữ liệu, hệ thống hiển thị message: “Không còn giao dịch nào.”
7️⃣ Acceptance Criteria mẫu
User Story
As a user, I want to view my transaction history in smaller batches so that the list loads quickly and is easy to browse.
Acceptance Criteria
When user opens transaction history, system loads the latest 20 transactions.
Transactions are sorted by
transactionTimedescending.When user clicks “Load more”, system loads the next 20 older transactions.
System must not display duplicate transactions across pages.
System must not skip transactions when loading more.
If no more transactions are available, system displays “No more transactions.”
If API loading fails, system shows an error message and allows retry.
8️⃣ Business Rule cần ghi rõ
Ví dụ:
BR-01: Default page size = 20 records.
BR-02: Maximum page size = 50 records.
BR-03: Transaction history is sorted by transaction time descending.
BR-04: User can query transaction history within the last 12 months.
BR-05: Each transaction must appear only once in the list.
9️⃣ NFR cần chú ý
Pagination liên quan trực tiếp đến performance.
Ví dụ NFR:
API must return paginated transaction list within ≤ 2 seconds for 95% of requests.
System must support loading transaction history for users with at least 10,000 records.
Pagination must prevent duplicate or missing records when new transactions are created during browsing.
📌 Đây là phần rất quan trọng, vì pagination không chỉ để “chia trang”, mà để hệ thống vẫn chạy ổn khi dữ liệu lớn.
🔟 Checklist BA khi viết Pagination
Trước khi chốt requirement, hãy tự hỏi:
Mỗi lần load bao nhiêu bản ghi?
Dùng page number hay cursor?
Sort theo field nào?
Có filter theo ngày/trạng thái không?
Khi load thêm có bị trùng bản ghi không?
Khi dữ liệu mới phát sinh có bị mất bản ghi không?
Khi hết dữ liệu hiển thị gì?
Khi API lỗi có retry không?
Có giới hạn thời gian truy vấn không?
Performance kỳ vọng là bao nhiêu giây?
Kết cục:
Danh sách đơn hàng, giao dịch, thông báo, lịch sử thanh toán… không nên load tất cả một lần.
Với BA, pagination không phải chi tiết kỹ thuật nhỏ.
Nó là requirement quan trọng để đảm bảo:
App load nhanh
API không bị quá tải
User xem dữ liệu mượt
Không trùng/mất bản ghi
QA test được rõ ràng
BA giỏi không viết:
“Hiển thị toàn bộ danh sách.”
BA giỏi viết:
“Hiển thị danh sách theo từng batch, có page size, sort order, load more, error handling và rule tránh duplicate/missing data.”
Đó mới là requirement đủ rõ để Dev build và QA test.
Học đầy đủ kiến thức để trở thành ITBA cho người mới bắt đầu -> Hướng dẫn áp dụng thực hành dự án để ghi vào CV (Quà tặng hơn 30 khóa ở đây):
=> https://www.facebook.com/groups/3514587515337829/posts/3618897148240198/
Đã có kiến thức BA cơ bản thì học các Khóa học chuyên sâu về các domain cùng case study thực tế: Bảo hiểm - ERP - Banking - E-commerce - Chính Phủ (GOV) - Logistis, tìm hiểu tại đây:
https://www.facebook.com/groups/3514587515337829/posts/3714548542008391



