DataTables Server-Side Pagination Not Updating: Diagnostic Guide
A diagnostic guide for DataTables 1.10+ server-side processing: inspect XHR parameters, validate draw/counts/data JSON, fix pagination and sorting, and know when to escalate.
26 Aug 2026, 23:21 UTC

When the table loads once and then stops responding
DataTables 1.10+ server-side processing turns pagination, sorting, and search into AJAX requests. If the first page renders but Next does nothing, or the table stays on "Loading...", the problem is usually in the request/response contract, not the rendering layer. The useful takeaway: inspect the XHR request and the JSON response before touching table CSS or event handlers.
Recognizable conditions and likely causes
| Condition | Likely cause | First check |
|---|---|---|
| Loading... indefinitely | AJAX 4xx/5xx, invalid JSON, wrong URL | Network tab XHR status and response body |
| Rows render but pagination does nothing | draw not echoed or client state reset | Response draw equals request draw |
| Sort/filter ignored | order/search parameters not mapped server-side | Request query string includes order[0][column], order[0][dir], search[value] |
| First page correct, later pages duplicate/missing | start/length not applied to SQL | Server query uses start and length placeholders |
| Console JSON parse error | Serializer wraps data or emits HTML/notice | Content-Type and raw response |
Ordered checks
1. Confirm one processing mode
DataTables can source rows from DOM, JavaScript array, or server-side AJAX. Mixing server-side: true with data already in the table or with ajax returning a nonstandard shape causes silent failures. In your initialization, serverSide: true must be paired with an ajax URL or function and columns definitions. Remove any data option that seeds rows when using server-side processing.
$('#example').DataTable({
serverSide: true,
ajax: {
url: '/api/orders',
type: 'GET'
},
columns: [
{ data: 'id' },
{ data: 'customer' },
{ data: 'total' }
]
});
This is an initialization example, not a tested deployment. The endpoint path and column names must match your application.
2. Inspect the XHR request parameters
Open browser developer tools, Network tab, filter XHR/Fetch, reload, and click Next. A server-side request should carry draw, start, length, search[value], order[0][column], order[0][dir], and columns[i][data] / columns[i][searchable] / columns[i][orderable] parameters. If those are absent, DataTables is not in server-side mode or the ajax option is not being used.
Check that start increments by length on each page. For page 2 with length 25, start should be 25. If start stays 0, the client is not updating state; if start jumps incorrectly, inspect any custom ajax.data function that overwrites parameters.
3. Validate the response contract
The server must return JSON with draw, recordsTotal, recordsFiltered, and data. draw must be the exact value from the request, not a string unless the client also treats it as one. recordsTotal is the count before filtering; recordsFiltered is the count after search/filter conditions; data is the current page array. A response missing any of these fields often leaves the table loading or breaks pagination.
{
"draw": 2,
"recordsTotal": 143,
"recordsFiltered": 143,
"data": [
{ "id": 26, "customer": "Acme", "total": "120.00" }
]
}
This is an illustrative shape, not captured output. The data array length should equal length except on the final page, where it can be smaller. If data contains more rows than length, the server is ignoring pagination.
4. Check server-side pagination and ordering
If draw and counts are correct but pages duplicate or skip rows, the SQL or data access query is likely not applying start and length, or it is applying them without a deterministic ORDER BY. Server-side processing expects the server to sort and slice. A query that returns rows in arbitrary order can produce duplicates across pages because the database is free to return a different order for each request.
Map order[0][column] to a safe column name using a whitelist, then append ORDER BY. Do not concatenate raw request values into SQL. Use parameterized LIMIT/OFFSET or your ORM's skip/take equivalent. If the table has a default sort, make sure the server applies the same default when no order parameter is present.
5. Look for serialization wrappers and casing changes
Some frameworks serialize responses with an outer envelope, such as { "result": { ... } } or { "d": { ... } }, or change property names to camelCase. DataTables expects the fields at the top level with the exact names draw, recordsTotal, recordsFiltered, and data. If your serializer emits records_total or Data, the client will not find them. Check the raw response body, not the framework's debug view.
Also confirm Content-Type is application/json. If PHP notices, HTML error pages, or BOM characters precede the JSON, the client reports a parse error even when the HTTP status is 200.
6. Reproduce the request outside the browser
Run this from a terminal on a machine that can reach the endpoint. Replace the URL and query values with those from the failing XHR. No special permissions are required for a GET request, but use a test account or token if the endpoint requires authentication. Avoid sending production credentials in shell history.
curl -i -G 'https://example.test/api/orders' --data-urlencode 'draw=2' --data-urlencode 'start=25' --data-urlencode 'length=25' --data-urlencode 'search[value]=' --data-urlencode 'order[0][column]=0' --data-urlencode 'order[0][dir]=asc'
Expected check: HTTP 200 and a JSON body with draw equal to 2 and a data array no longer than 25 items. If curl returns HTML, a redirect, or a different draw value, fix the endpoint before changing DataTables options. Risk: the endpoint may expose data; use a non-production dataset when possible.
Fixes tied to findings
- Missing server-side parameters: set serverSide: true and ensure ajax is configured; remove DOM data sources.
- draw mismatch: return the request draw unchanged; do not increment or hard-code it.
- Wrong counts: compute recordsTotal without filters and recordsFiltered with the same filters used for the data query.
- Duplicate or missing rows: add a stable ORDER BY and apply start/length in the database query.
- Parse error: fix serialization wrappers, casing, and Content-Type; suppress notices that print before JSON.
- Sort/filter ignored: map order and search parameters to whitelisted columns and parameterized conditions.
Escalation criteria
Escalate to the backend owner if the XHR request contains the expected parameters but the server returns a different draw, non-JSON content, or counts that cannot be reconciled with the data query. Escalate to the frontend owner if the request lacks start, length, or order parameters even though serverSide: true is set. Escalate to database/query review if the server returns valid JSON but page boundaries overlap or skip rows with a stable ORDER BY. For intermittent failures, capture the failing draw value, request timestamp, and response body; those three details usually distinguish caching, race conditions, and query errors.
Limitations and verification
This guide assumes DataTables 1.10+ with server-side processing and a JSON endpoint. It does not cover Editor, Scroller, or custom data loaders, which can change the request lifecycle. To verify a fix, reload the table, click through first, middle, and last pages, apply a search that reduces recordsFiltered, and confirm the Network tab shows a new request for each action with matching draw values. If the table uses state saving, clear saved state or test in a private window so old parameters do not mask the result.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.