Understanding AG-Grid Row Models: Client-Side vs. Server-Side
AG-Grid is a highly performant and feature-rich data grid that offers various ways to handle and display data. At the heart of how AG-Grid manages its rows lies the concept of a "Row Model." The row model determines how data is fetched, processed, and presented to the user. Choosing the right row model is a critical decision that impacts your application's performance, scalability, and implementation complexity, especially when working with React.
In this post, part of our AG-Grid-React series, we'll dive deep into the two most commonly used row models: the Client-Side Row Model and the Server-Side Row Model. We'll explore their mechanisms, ideal use cases, advantages, disadvantages, and provide React code examples for each.
1. The Client-Side Row Model: Simplicity and Speed for Smaller Datasets
The Client-Side Row Model is the default and simplest row model in AG-Grid. It's designed for scenarios where your entire dataset can be loaded into the browser's memory at once.
How it Works
-
All Data Upfront: When using the client-side model, you provide AG-Grid with all the data
it needs to display, typically via the
rowDataprop. - Client-Side Processing: Once the data is loaded, all operations such as sorting, filtering, grouping, and aggregation are performed directly within the browser using JavaScript.
When to Use It
This model is ideal for:
- Datasets up to a few thousand rows (typically less than 10,000, depending on row complexity).
- Applications where all necessary data can be easily fetched and held in client memory.
- Scenarios where rapid client-side interactivity (instant sorting, filtering) is a priority.
- Prototypes or smaller applications with less stringent scalability requirements.
Advantages
-
Ease of Implementation: It requires minimal setup. Just provide the
rowData, and AG-Grid handles the rest. - Performance (Small Data): For smaller datasets, operations like sorting and filtering are extremely fast, as no network requests are involved after the initial load.
- Feature Rich: All built-in AG-Grid features (sorting, filtering, grouping, pagination, pivot) work seamlessly out-of-the-box without any server-side configuration.
Disadvantages
- Scalability Issues: Performance can degrade significantly with large datasets (tens of thousands of rows or more), leading to sluggish UI and longer initial load times.
- Memory Consumption: Loading all data into the browser's memory can lead to high memory consumption, potentially causing the browser to slow down or crash.
- Initial Load Time: If the dataset, even if manageable, is large in terms of data transfer, the initial load time can be slower as all data must be downloaded first.
Client-Side Row Model Example (React)
Here's a basic React component demonstrating the Client-Side Row Model. Notice how rowData is
simply passed to the grid, and rowModelType defaults to 'clientSide'.
import React, { useState, useMemo } from 'react';
import { AgGridReact } from 'ag-grid-react';
// Import AG-Grid styles
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
const ClientSideGrid = () => {
// Define your row data (all data loaded upfront)
const [rowData] = useState([
{ make: "Toyota", model: "Celica", price: 35000 },
{ make: "Ford", model: "Mondeo", price: 32000 },
{ make: "Porsche", model: "Boxster", price: 72000 },
{ make: "BMW", model: "M5", price: 60000 },
{ make: "Audi", model: "A4", price: 45000 },
{ make: "Mercedes", model: "C-Class", price: 50000 },
// ... add more data as needed
]);
// Define column definitions
const [columnDefs] = useState([
{ field: 'make', sortable: true, filter: true },
{ field: 'model', sortable: true, filter: true },
{ field: 'price', sortable: true, filter: 'agNumberColumnFilter' }
]);
// Default column properties
const defaultColDef = useMemo(() => ({
flex: 1,
minWidth: 100,
resizable: true,
}), []);
return (
<div className="ag-theme-alpine" style={{ height: 400, width: 600 }}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
// rowModelType is 'clientSide' by default, explicit for clarity
rowModelType="clientSide"
pagination={true}
paginationPageSize={10}
/>
</div>
);
};
export default ClientSideGrid;
2. The Server-Side Row Model: Powering Large and Complex Data Grids
The Server-Side Row Model (SSRM) is an enterprise-level feature of AG-Grid designed to handle truly massive datasets, often tens of thousands to millions of rows. Instead of loading all data at once, it delegates data fetching and processing to a backend server.
How it Works
- Data on Demand: Data is fetched from the server only when it's needed to be displayed, typically in "blocks" or "pages."
- Server-Side Processing: User interactions like sorting, filtering, grouping, and pagination trigger a request to the server. The server processes these operations and returns only the relevant subset of data.
-
Datasource Interface: You implement a
serverSideDatasourceinterface that AG-Grid uses to make requests to your backend API.
When to Use It
The Server-Side Row Model is essential for:
- Datasets with tens of thousands to millions of rows.
- When data security or access control requires server-side validation for every data request.
- When complex data processing (e.g., aggregations over massive datasets) is best handled by a powerful backend.
- Applications where you need to minimize the client's memory footprint.
Advantages
- Scalability: Handles virtually unlimited datasets, making it suitable for enterprise applications with huge data volumes.
- Low Client Memory Footprint: Only a small subset of data (the visible rows and cached blocks) is ever held in the browser's memory, preventing performance bottlenecks.
- Custom Logic: Provides full control over how data is fetched, sorted, filtered, and grouped on the server, allowing for highly optimized and secure data operations.
- Security: Data remains secure on the server until explicitly requested by the grid, enabling fine-grained access control.
Disadvantages
- Implementation Complexity: Requires significant server-side development to build the data API that can handle sorting, filtering, pagination, and grouping requests from the grid.
- Increased Latency: Each user action (sorting, filtering, pagination) involves a server round trip, which can introduce slight delays compared to instant client-side operations.
- Development Effort: More initial setup and ongoing maintenance are needed due to the client-server integration.
Server-Side Row Model Example (React)
This React example shows how to configure AG-Grid for the Server-Side Row Model. Note the
rowModelType="serverSide" and the implementation of a serverSideDatasource.
The fetchServerData function would typically be an actual API call to your backend.
import React, { useState, useMemo, useCallback } from 'react';
import { AgGridReact } from 'ag-grid-react';
// Import AG-Grid styles
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
// --- Mock API Call (Simulates your backend) ---
// In a real application, this would be an actual fetch request to your server API.
const fetchServerData = (request) => {
console.log('Sending request to server:', request);
return new Promise((resolve) => {
setTimeout(() => { // Simulate network latency
// This is a mock dataset on the "server"
const allData = Array.from({ length: 100000 }, (_, i) => ({
id: i + 1,
name: `Product ${i + 1}`,
value: Math.floor(Math.random() * 1000)
}));
let processedData = [...allData];
// 1. Apply Server-Side Filtering
if (request.filterModel && request.filterModel.name && request.filterModel.name.filter) {
const filterText = request.filterModel.name.filter.toLowerCase();
processedData = processedData.filter(item => item.name.toLowerCase().includes(filterText));
}
// 2. Apply Server-Side Sorting
if (request.sortModel.length > 0) {
const { colId, sort } = request.sortModel[0];
processedData.sort((a, b) => {
const valA = a[colId];
const valB = b[colId];
if (valA < valB) return sort === 'asc' ? -1 : 1;
if (valA > valB) return sort === 'asc' ? 1 : -1;
return 0;
});
}
// 3. Apply Server-Side Pagination
const totalRows = processedData.length;
const rowsThisPage = processedData.slice(request.startRow, request.endRow);
resolve({
rows: rowsThisPage,
totalRows: totalRows,
});
}, 700);
});
};
// --- End Mock API Call ---
const ServerSideGrid = () => {
const [columnDefs] = useState([
{ field: 'id', headerName: 'ID', filter: true, sortable: true },
{ field: 'name', headerName: 'Product Name', filter: true, sortable: true },
{ field: 'value', headerName: 'Value', filter: true, sortable: true }
]);
const defaultColDef = useMemo(() => ({
flex: 1,
minWidth: 100,
resizable: true,
}), []);
// AG-Grid calls this function to get the datasource interface
const getServerSideDatasource = useCallback(() => {
return {
getRows: (params) => {
// params.request contains info about what the grid needs (startRow, endRow, sortModel, filterModel)
fetchServerData(params.request)
.then(response => {
// On successful fetch, pass data and total row count back to the grid
params.successCallback(response.rows, response.totalRows);
})
.catch(error => {
console.error('Error fetching server-side data:', error);
params.failCallback(); // Notify grid of failure
});
},
};
}, []);
const onGridReady = useCallback((params) => {
// Set the server-side datasource once the grid API is available
params.api.setServerSideDatasource(getServerSideDatasource());
}, [getServerSideDatasource]);
return (
<div className="ag-theme-alpine" style={{ height: 500, width: '100%' }}>
<AgGridReact
columnDefs={columnDefs}
defaultColDef={defaultColDef}
rowModelType="serverSide" // Crucial for server-side operations
onGridReady={onGridReady}
pagination={true} // Enable pagination
paginationPageSize={100} // Number of rows per "page"
cacheBlockSize={100} // Number of rows to fetch per block from server
/>
</div>
);
};
export default ServerSideGrid;
3. Client-Side vs. Server-Side: A Quick Comparison
Here's a concise overview of the key differences between the two row models:
-
Data Loading:
- Client-Side: All data is loaded into the browser at once.
- Server-Side: Data is loaded incrementally, on demand, from the server.
-
Processing Location:
- Client-Side: Sorting, filtering, grouping, etc., are handled by the browser.
- Server-Side: Sorting, filtering, grouping, etc., are delegated to the backend server.
-
Scalability:
- Client-Side: Limited to small to medium datasets (typically < 10,000 rows).
- Server-Side: Highly scalable, handles massive datasets (> 100,000 to millions of rows).
-
Memory Footprint (Client):
- Client-Side: High, as all data resides in the browser's memory.
- Server-Side: Low, only visible data and a few cached blocks are in memory.
-
Implementation Complexity:
- Client-Side: Relatively simple, mostly frontend configuration.
- Server-Side: More complex, requires significant frontend-backend integration.
-
Performance Impact:
- Client-Side: Very fast operations for small data; slow for large data.
- Server-Side: Consistent performance for large data, but operations involve network latency.
4. Choosing the Right Row Model for Your AG-Grid Application
The decision between the Client-Side and Server-Side Row Model is crucial and should be based on your specific application requirements:
- Dataset Size: This is often the primary factor. If you expect to display thousands of rows or more, the Server-Side Row Model is almost always the correct choice for performance and scalability. For hundreds or a few thousand rows, Client-Side is simpler and often performs faster due to no network round-trips.
- Performance Requirements: Do your users demand instant feedback on sorting and filtering, or is a slight delay acceptable for the ability to browse massive datasets?
- Development Resources: Do you have the backend expertise and resources to build and maintain a robust API for server-side operations? The Client-Side Row Model significantly reduces backend work for the grid.
- Feature Set: Do you need advanced server-side grouping, aggregations, or complex business logic tied to data access that only a backend can provide efficiently?
- Data Security: If your data contains sensitive information that should not be transferred entirely to the client, the Server-Side Row Model, fetching only what's needed, is paramount.
Conclusion
AG-Grid's flexible row models empower you to build powerful and responsive data tables, regardless of your dataset size. The Client-Side Row Model offers simplicity and speed for smaller, manageable data. In contrast, the Server-Side Row Model provides unparalleled scalability and control for enterprise-grade applications dealing with vast amounts of data, albeit with increased implementation complexity.
By carefully considering your data volume, performance expectations, and development resources, you can select the optimal row model to ensure your AG-Grid React applications deliver an excellent user experience. Understanding this fundamental difference is key to mastering AG-Grid and building truly performant data solutions.