Description
When displaying 100+ items in a list view (e.g. Product model), the full SSR approach causes extremely high CPU usage on small servers (2 vCPU), making the page take 10+ seconds to load. The server CPU spikes to 140% during rendering.
The page should load in under 2 seconds, similar to other admin panels (Django Admin, AdminJS, Strapi) handling the same data volume.
Actual behavior
100 items: ~25s response time, CPU at 140%
50 items: acceptable but still slow (~5-8s)
25 items: fine
The bottleneck is not the database (queries return in <100ms). It is the SSR rendering: React renders 100+ table rows server-side, serializes them to HTML, then the client rehydrates everything.
Would it be possible to support a client-side pagination mode, where:
The server sends a lightweight JSON response (just the data)
The table rendering and pagination happen entirely on the client side
Only the data fetching goes through the server (API route)
This would be similar to how AdminJS or Strapi work : the server only acts as an API, and the browser handles the rendering. This would drastically reduce server CPU usage for list views.
Currently, i reduce defaultListSize to 25-50 and relying on pagination, but this limits the user experience
Reproduction URL
https://github.com/Manon-Arc/Test-nextAdmin.git
Reproduction steps
1. Configure a model with defaultListSize: 100 or higher
2. The model displays ~8 columns including 3 relations (entity, category, sub_category) with custom formatter
3. Load the list page on a 2 vCPU server
For example :
model Product {
id Int @id @default(autoincrement())
name String @db.VarChar(255)
reference String @unique(map: "reference") @db.VarChar(100)
buying_price Decimal @db.Decimal(10, 2)
buying_price_sub Decimal @db.Decimal(10, 2)
image_url String? @db.VarChar(255)
hide Boolean @default(false)
id_category Int
id_sub_category Int
id_entity Int
category Category @relation(fields: [id_category], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "products_ibfk_1")
sub_category Sub_category @relation(fields: [id_sub_category], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "products_ibfk_2")
entity Entity @relation(fields: [id_entity], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "products_ibfk_3")
quotation_line Quotation_line[]
attribut_value Attribut_value[]
@@index([reference], map: "reference_2")
@@index([id_category], map: "idx_product_id_category")
@@index([id_sub_category], map: "idx_product_id_sub_category")
@@index([id_entity], map: "idx_product_id_entity")
@@map("product")
}
Next router
App router
Next Admin version
8.4.2
Screenshots
Next Admin options
Product: {
title: "Produits",
icon: "ShoppingBagIcon",
toString: (product) => `${product.name} (${product.reference})`,
list: {
defaultListSize: 150,
search: ["name", "reference"] as any,
display: ["id", "name", "reference", "buying_price", "buying_price_sub", "hide", "entity", "category", "sub_category"],
fields: {
entity: {
formatter: (entity) => {
return entity?.name || "Entité inconnue";
},
},
category: {
formatter: (category) => {
return category?.name || "Catégorie inconnue";
},
},
sub_category: {
formatter: (sub_category) => {
return sub_category ? `${sub_category.name} (${sub_category.type})` : "Sous-catégorie inconnue";
},
},
},
},
edit: {
display: ["name", "reference", "buying_price", "buying_price_sub", "hide", "entity", "category", "sub_category"],
hooks: {
beforeDb: async (data, mode) => {
if (data.reference) {
data.reference = data.reference.toString().trim();
}
if (data.name) {
data.name = data.name.toString().trim();
}
return data;
},
},
},
},
Logs
Browsers
No response
Description
When displaying 100+ items in a list view (e.g. Product model), the full SSR approach causes extremely high CPU usage on small servers (2 vCPU), making the page take 10+ seconds to load. The server CPU spikes to 140% during rendering.
The page should load in under 2 seconds, similar to other admin panels (Django Admin, AdminJS, Strapi) handling the same data volume.
Actual behavior
100 items: ~25s response time, CPU at 140%
50 items: acceptable but still slow (~5-8s)
25 items: fine
The bottleneck is not the database (queries return in <100ms). It is the SSR rendering: React renders 100+ table rows server-side, serializes them to HTML, then the client rehydrates everything.
Would it be possible to support a client-side pagination mode, where:
The server sends a lightweight JSON response (just the data)
The table rendering and pagination happen entirely on the client side
Only the data fetching goes through the server (API route)
This would be similar to how AdminJS or Strapi work : the server only acts as an API, and the browser handles the rendering. This would drastically reduce server CPU usage for list views.
Currently, i reduce defaultListSize to 25-50 and relying on pagination, but this limits the user experience
Reproduction URL
https://github.com/Manon-Arc/Test-nextAdmin.git
Reproduction steps
Next router
App router
Next Admin version
8.4.2
Screenshots
Next Admin options
Logs
Browsers
No response