8 min

Listas rápidas en paneles con 100k filas: qué hacer primero

Aprende a construir listas rápidas en dashboards con 100k filas usando paginación, virtualización, filtros inteligentes y mejores consultas para que las herramientas internas sigan siendo ágiles.

Listas rápidas en paneles con 100k filas: qué hacer primero

Por qué las pantallas de lista se ralentizan a medida que crecen los datos

Una pantalla de lista suele sentirse bien hasta que deja de hacerlo. Los usuarios empiezan a notar pequeños tartamudeos que se acumulan: el desplazamiento se corta, la página se queda un momento después de cada actualización, los filtros tardan segundos en responder y aparece un spinner tras cada clic. A veces la pestaña del navegador parece congelada porque el hilo de la UI está ocupado.

100k filas es un punto de inflexión común porque estresa todas las partes del sistema a la vez. El conjunto de datos sigue siendo normal para una base de datos, pero lo suficientemente grande como para hacer obvias las pequeñas ineficiencias en el navegador y en la red. Si intentas mostrarlo todo a la vez, una pantalla simple se convierte en una tubería pesada.

El objetivo no es renderizar todas las filas. El objetivo es ayudar a alguien a encontrar lo que necesita rápido: las 50 filas correctas, la siguiente página o una porción estrecha basada en un filtro.

Ayuda dividir el trabajo en cuatro partes:

  • Red: cuántos bytes envías y con qué frecuencia.
  • Base de datos: cuánto datos escaneas, ordenas y agregas por petición.
  • Renderizado en el navegador: cuántos nodos DOM creas, mides y pintas.
  • Trabajo en JavaScript: con qué frecuencia re-renderizas, recalculas columnas o recomputas resultados.

Si cualquiera de esas partes es cara, toda la pantalla se siente lenta. Una búsqueda simple puede disparar una petición que ordena 100k filas, devuelve miles de registros y luego fuerza al navegador a renderizarlos todos. Así es como escribir se vuelve lento.

Cuando los equipos construyen herramientas internas rápido (incluso con plataformas de low-code como Koder.ai), las pantallas de lista suelen ser el primer lugar donde el crecimiento real de datos expone la brecha entre “funciona con un dataset de demo” y “se siente instantáneo todos los días”.

Elige el objetivo de rendimiento correcto

Antes de optimizar, decide qué significa "rápido" para esta pantalla. Muchos equipos persiguen el throughput (cargar todo) cuando los usuarios necesitan sobre todo baja latencia (ver algo actualizarse rápido). Una lista puede sentirse instantánea aunque nunca cargue las 100k filas, siempre que responda rápido al desplazamiento, orden y filtros.

Un objetivo práctico es el tiempo hasta la primera fila, no el tiempo hasta carga completa. Los usuarios confían en la página cuando ven las primeras 20 a 50 filas rápido y las interacciones se mantienen fluidas.

Qué medir (y por qué)

Elige un pequeño conjunto de números que puedas rastrear cada vez que cambias algo:

  • Tiempo hasta la primera fila tras abrir la página o cambiar un filtro
  • Tiempo para que un filtro u orden muestre resultados actualizados
  • Tamaño de la respuesta (tamaño aproximado del payload JSON)
  • Consultas lentas (especialmente COUNT(*) y SELECTs amplios)
  • Picos en el hilo principal del navegador (tartamudeo al desplazar, retardo al escribir)

Estos mapean los síntomas comunes. Si la CPU del navegador se dispara al desplazarte, el frontend está haciendo demasiado trabajo por fila. Si el spinner espera pero el desplazamiento va bien después, el problema suele estar en backend o la red. Si la petición es rápida pero la página sigue congelándose, casi siempre es renderizado o procesamiento pesado del lado del cliente.

Una prueba rápida frontend vs backend

Prueba un experimento simple: mantiene la UI igual, pero limita temporalmente el backend para que devuelva solo 20 filas con los mismos filtros. Si se vuelve rápido, tu cuello de botella es el tamaño de carga o el tiempo de consulta. Si sigue lento, revisa renderizado, formateo y componentes por fila.

Ejemplo: una pantalla interna de Orders se siente lenta cuando escribes en la búsqueda. Si la API devuelve 5.000 filas y el navegador las filtra en cada pulsación, escribir se retrasará. Si la API tarda 2 segundos por un COUNT en un filtro sin índice, verás espera antes de que cambie cualquier fila. Diferentes soluciones, misma queja del usuario.

Fundamentos del frontend: mantener el render barato

El navegador es a menudo el primer cuello de botella. Una lista puede sentirse lenta incluso cuando la API es rápida, simplemente porque la página intenta pintar demasiado. La primera regla es simple: no renderices miles de filas en el DOM a la vez.

Incluso antes de añadir virtualización completa, mantén cada fila ligera. Una fila con contenedores anidados, iconos, tooltips y estilos condicionales complejos en cada celda te cuesta en cada desplazamiento y actualización. Prefiere texto plano, un par de badges pequeños y solo uno o dos elementos interactivos por fila.

La altura de fila estable ayuda más de lo que parece. Cuando cada fila tiene la misma altura, el navegador puede predecir el layout y el desplazamiento se mantiene suave. Las filas de altura variable (descripciones que hacen wrap, notas expansibles, avatares grandes) disparan mediciones extra y reflow. Si necesitas detalles adicionales, considera un panel lateral o un área expandible única, no una fila multilínea completa.

El formateo es otro coste silencioso. Fechas, moneda y trabajo pesado de strings se acumulan cuando se repiten en muchas celdas.

Regla práctica

Si un valor no es visible, no lo calcules todavía. Cachea resultados de formateo caros y calcúlalos bajo demanda, por ejemplo cuando una fila se vuelve visible o cuando el usuario abre una fila.

Un repaso rápido que suele dar una mejora notable:

  • Limita el render inicial a una página pequeña (o una ventana virtual)
  • Mantén la altura de fila fija y evita celdas multilínea
  • Mueve UI pesada (tooltips, menús) a hover o click
  • Memoiza o cachea el formateo de fechas y monedas por fila
  • Evita re-renderizar todas las filas cuando cambia solo un filtro

Ejemplo: una tabla interna de Invoices que formatea 12 columnas de moneda y fechas tartamudea al desplazar. Cachear los valores formateados por factura y retrasar el trabajo para filas fuera de pantalla puede hacer que se sienta instantáneo, incluso antes de trabajar más en el backend.

Virtualización: cómo desplazar 100k filas de forma fluida

Virtualización significa que la tabla solo dibuja las filas que realmente puedes ver (más un pequeño buffer arriba y abajo). A medida que te desplazas, reutiliza los mismos elementos DOM y cambia los datos dentro de ellos. Eso evita que el navegador intente pintar decenas de miles de componentes de fila a la vez.

La virtualización encaja bien cuando tienes listas largas, tablas anchas o filas pesadas (avatares, chips de estado, menús de acción, tooltips). También es útil cuando los usuarios se desplazan mucho y esperan una vista continua y suave en lugar de saltar página por página.

Dónde la virtualización se complica

No es magia. Unas cuantas cosas suelen causar sorpresas:

  • Las alturas de fila variables (texto que hace wrap, filas expansibles) pueden romper el desplazamiento suave a menos que midas alturas o mantengas filas de tamaño consistente.
  • Cabeceras y columnas sticky pueden entrar en conflicto con el contenedor virtualizado si el layout depende de CSS complejo.
  • La navegación por teclado (arriba/abajo, page up/down, focus en celdas) necesita cuidado extra para que el foco no salte a filas desmontadas.
  • Las acciones masivas necesitan una regla clara: seleccionar filas visibles, seleccionar según filtros o seleccionar todo el conjunto.

El enfoque más sencillo es aburrido: altura de fila fija, columnas predecibles y no demasiados widgets interactivos dentro de cada fila.

Virtualización más paginación (sin confundir al usuario)

Puedes combinar ambas: usa paginación (o carga por cursor) para limitar lo que obtienes del servidor, y virtualización para mantener barato el render dentro del fragmento obtenido.

Un patrón práctico es obtener una página normal (a menudo 100 a 500 filas), virtualizar dentro de esa página y ofrecer controles claros para moverse entre páginas. Si usas scroll infinito, añade un indicador visible “Cargadas X de Y” para que los usuarios entiendan que no están viendo todo todavía.

Opciones de paginación que se mantienen rápidas

Envía paginación primero
Crea una lista de dashboard con paginación, filtros y valores por defecto sensatos en minutos.

Si necesitas una pantalla de lista que siga siendo usable conforme crecen los datos, la paginación suele ser la opción por defecto más segura. Es predecible, funciona bien para flujos administrativos (revisar, editar, aprobar) y soporta necesidades comunes como exportar “página 3 con estos filtros” sin sorpresas. Muchos equipos vuelven a la paginación después de probar scrolls más complejos.

El scroll infinito puede sentirse bien para navegación casual, pero tiene costes ocultos. La gente pierde la noción de dónde está, el botón de atrás no suele devolverlos al mismo punto y las sesiones largas pueden acumular memoria a medida que se cargan más filas. Un punto medio es un botón Cargar más que siga usando páginas, de modo que los usuarios se mantengan orientados.

Offset vs keyset pagination

La paginación por offset es el clásico page=10&size=50. Es simple, pero puede volverse más lenta en tablas grandes porque la base de datos puede tener que saltarse muchas filas para llegar a páginas posteriores. Además puede comportarse extraño cuando llegan filas nuevas y los items cambian de página.

La paginación por keyset (a menudo llamada cursor) pide “las siguientes 50 filas después del último elemento visto”, normalmente usando un id o created_at. Suele mantenerse rápida porque no necesita contar ni saltarse tantas filas.

Una regla práctica:

  • Usa offset para listas más pequeñas, datasets estables y cuando necesitas saltar a un número de página exacto.
  • Usa keyset para listas muy grandes, inserciones frecuentes y navegación Siguiente/Anterior.

Mostrar totales sin pagar el precio cada vez

A los usuarios les gusta ver totales, pero un "contar todas las filas que coinciden" puede ser caro con filtros complejos. Opciones: cachear conteos para filtros populares, actualizar el conteo en segundo plano después de cargar la página, o mostrar un conteo aproximado (por ejemplo, "10.000+").

Ejemplo: una pantalla interna de Orders puede mostrar resultados al instante con paginación por keyset y luego completar el total exacto solo cuando el usuario deja de cambiar filtros por un segundo.

Si estás construyendo esto en Koder.ai, trata la paginación y el comportamiento del conteo como parte de la especificación de la pantalla desde el inicio, para que las consultas generadas y el estado UI no choquen más tarde.

Filtros y búsquedas que se sienten instantáneos

La mayoría de pantallas de lista se sienten lentas porque empiezan demasiado abiertas: cargan todo y luego piden al usuario que lo estreche. Dale la vuelta. Empieza con valores por defecto sensatos que devuelvan un conjunto pequeño y útil (por ejemplo: Últimos 7 días, Mis elementos, Estado: Abierto) y haz de “Todo el tiempo” una elección explícita.

La búsqueda por texto es otra trampa común. Si ejecutas una consulta en cada pulsación, creas una cola de peticiones y una UI que parpadea. Debouncea la entrada de búsqueda para consultar solo después de que el usuario haga una pausa breve y cancela peticiones anteriores cuando empieza una nueva. Una regla simple: si el usuario todavía está escribiendo, no consultes el servidor aún.

Los filtros solo se sienten rápidos cuando también son claros. Muestra chips de filtro cerca de la tabla para que los usuarios vean qué está activo y lo eliminen con un clic. Mantén las etiquetas humanas, no nombres de campo crudos (por ejemplo, Owner: Sam en lugar de owner_id=42). Cuando alguien dice “mis resultados desaparecieron”, suele deberse a un filtro invisible.

Patrones que mantienen listas grandes responsivas sin complicar la UI:

  • Por defecto usa filtros estrechos y un rango de fecha corto
  • Debouncea la búsqueda por texto y cancela peticiones en curso
  • Muestra chips de filtro y una acción Borrar todo
  • Ofrece vistas guardadas para trabajos comunes
  • Bloquea filtros caros hasta que haya al menos un filtro que reduzca

Las vistas guardadas son la heroína silenciosa. En lugar de enseñar a los usuarios a construir combinaciones perfectas de filtros cada vez, dales presets que coincidan con flujos reales. Un equipo de ops podría alternar entre Pagos fallidos hoy y Clientes de alto valor. Eso puede ser un clic, entendible al instante y más fácil de mantener rápido en el backend.

Si estás construyendo una herramienta interna en un constructor guiado por chat como Koder.ai, trata los filtros como parte del flujo de producto, no como un añadido. Empieza por las preguntas más comunes y diseña la vista por defecto y las vistas guardadas alrededor de esas.

Modelado de consultas: pide menos, calcula menos

Una pantalla de lista rara vez necesita los mismos datos que una página de detalle. Si tu API devuelve todo sobre todo, pagas dos veces: la base de datos hace más trabajo y el navegador recibe y renderiza más de lo que puede usar. Query shaping es el hábito de pedir solo lo que la lista necesita ahora mismo.

Empieza devolviendo solo las columnas necesarias para renderizar cada fila. Para la mayoría de dashboards eso es un id, un par de etiquetas, un estado, un propietario y timestamps. Texto grande, blobs JSON y campos computados pueden esperar hasta que el usuario abra una fila.

Evita joins pesados para la primera pintura. Los joins están bien cuando usan índices y devuelven resultados pequeños, pero se vuelven caros cuando unes varias tablas y luego ordenas o filtras sobre los datos unidos. Un patrón simple: obtén la lista de una tabla rápido y carga detalles relacionados bajo demanda (o por lotes para las filas visibles únicamente).

Mantén las opciones de orden limitadas y ordena por columnas indexadas. "Ordenar por cualquier cosa" suena útil, pero a menudo fuerza ordenaciones lentas en datasets grandes. Prefiere unas pocas opciones previsibles como created_at, updated_at o status y asegúrate de que esas columnas estén indexadas.

Ten cuidado con agregaciones del lado servidor. COUNT(*) sobre un conjunto filtrado grande, DISTINCT en una columna amplia o cálculos de páginas totales pueden dominar tu tiempo de respuesta.

Un enfoque práctico:

  • Modela la respuesta de la lista a 5–10 campos
  • Obtén detalles de fila solo cuando se abra la fila
  • Permite 2–4 opciones de orden, todas respaldadas por índices
  • Trata COUNT y DISTINCT como opcionales y cachea o aproxima cuando sea posible

Si construyes herramientas internas en Koder.ai, define una consulta ligera para la lista separada de la consulta de detalles en modo planificación, para que la UI siga siendo ágil a medida que crecen los datos.

Tácticas en la base de datos para tablas grandes

Prueba rendimiento en producción
Despliega y hospeda tu herramienta interna para que compañeros prueben con datos reales cuanto antes.

Si quieres una pantalla de lista que se mantenga rápida con 100k filas, la base de datos tiene que hacer menos trabajo por petición. La mayoría de listas lentas no son “demasiados datos”, son el patrón de acceso equivocado.

Empieza con índices que coincidan con lo que tus usuarios realmente hacen. Si tu lista normalmente se filtra por status y se ordena por created_at, necesitas un índice que soporte ambos, en ese orden. Si no, la base de datos puede escanear muchas más filas de lo esperado y luego ordenarlas, lo que se vuelve caro rápido.

Arreglos que suelen dar las mayores mejoras:

  • Añade índices compuestos que reflejen tu filtro + orden común (por ejemplo tenant_id, status, created_at).
  • Prefiere paginación por keyset (cursor) sobre OFFSET profundos. OFFSET hace que la BD recorra muchas filas solo para saltarlas.
  • Considera el conteo total como opcional. Los totales exactos pueden ser lentos en conjuntos filtrados grandes. Cachea conteos, pré-cálculos o muestra "10.000+" cuando no se necesitan números exactos.
  • Mantén las filas delgadas. No selecciones campos de texto grandes, blobs JSON o objetos anidados para la vista de lista.
  • Modela las consultas para devolver solo lo que la UI renderiza: unos pocos campos para la tabla más el cursor de la siguiente página.

Un ejemplo simple: una tabla interna de Orders que muestra nombre de cliente, estado, importe y fecha. No hagas join con cada tabla relacionada ni traigas las notas completas del pedido para la vista de lista. Devuelve solo las columnas usadas en la tabla y carga el resto en una petición separada cuando el usuario haga clic en un pedido.

Si construyes con una plataforma como Koder.ai, mantén esta mentalidad aunque la UI se genere desde chat. Asegúrate de que los endpoints API generados soporten paginación por cursor y campos selectivos, para que el trabajo en la BD sea predecible a medida que la tabla crece.

Plan paso a paso para acelerar una pantalla de lista existente

Si una página de lista se siente lenta hoy, no empieces reescribiendo todo. Comienza por definir cómo es el uso normal y luego optimiza ese camino.

Un plan práctico de cinco pasos

  1. Define la vista por defecto. Elige filtros por defecto, orden y columnas visibles. Las listas se vuelven lentas cuando intentan mostrarlo todo por defecto.

  2. Elige un estilo de paginación que coincida con el uso. Si los usuarios principalmente revisan las primeras páginas, la paginación clásica está bien. Si la gente salta muy profundo (página 200+) o necesitas rendimiento estable sin importar la profundidad, usa paginación por keyset (basada en un orden estable como created_at más un id).

  3. Añade virtualización para el cuerpo de la tabla. Incluso si el backend es rápido, el navegador puede bloquearse al renderizar demasiadas filas a la vez.

  4. Haz que la búsqueda y los filtros se sientan instantáneos. Debouncea la escritura para no disparar peticiones en cada pulsación. Mantén el estado de filtros en la URL o en un store compartido para que refresh, el botón atrás y compartir funcionen de forma fiable. Cachea el último resultado exitoso para que la tabla no parpadee vacía.

  5. Mide y luego afina consultas e índices. Registra tiempos de servidor, tiempo en la BD, tamaño de payload y tiempo de render. Luego recorta la consulta: selecciona solo las columnas que muestras, aplica filtros pronto y añade índices que coincidan con tu filtro + orden por defecto.

Ejemplo: un dashboard de soporte con 100k tickets. Por defecto muestra Abiertos, asignados a mi equipo, ordenados por más recientes, muestra seis columnas y solo obtiene id, asunto, asignado, estado y timestamps. Con paginación por keyset y virtualización, mantienes la base de datos y la UI predecibles.

Si construyes herramientas internas en Koder.ai, este plan encaja bien con un flujo iterar-y-comprobar: ajusta la vista, prueba desplazamiento y búsqueda, y luego afina la consulta hasta que la página se mantenga ágil.

Errores comunes que hacen que las listas vayan lentas

Optimiza el tiempo hasta la primera fila
Construye una lista de administrador que cargue las primeras 50 filas rápido y se mantenga sensible a filtros.

La forma más rápida de romper una pantalla de lista es tratar 100k filas como una página normal de datos. La mayoría de dashboards lentos caen en unas trampas previsibles.

Una grande es renderizar todo y ocultarlo con CSS. Aunque parezca que solo 50 filas son visibles, el navegador sigue pagando el coste de crear 100k nodos DOM, medirlos y repintar al desplazar. Si necesitas listas largas, renderiza solo lo que el usuario puede ver (virtualización) y mantén simples los componentes de fila.

La búsqueda también puede arruinar el rendimiento silenciosamente cuando cada pulsación dispara un escaneo completo de la tabla. Eso ocurre cuando los filtros no tienen índice, cuando buscas en demasiadas columnas o cuando haces consultas de tipo contains en campos de texto enormes sin un plan. Una buena regla: el primer filtro al que recurre el usuario debe ser barato en la BD, no solo conveniente en la UI.

Otro problema común es traer registros completos cuando la lista solo necesita resúmenes. Una fila de lista suele necesitar 5–12 campos, no todo el objeto, no descripciones largas y no datos relacionados. Traer datos extra aumenta trabajo en la BD, tiempo de red y parsing en el frontend.

Exportar y totales pueden congelar la UI si los calculas en el hilo principal o esperas una petición pesada antes de responder. Mantén la UI interactiva: inicia exportaciones en segundo plano, muestra progreso y evita recalcular totales en cada cambio de filtro.

Finalmente, demasiadas opciones de orden pueden salir mal. Si los usuarios pueden ordenar por cualquier columna, acabarás ordenando grandes conjuntos en memoria o forzando a la BD a planes lentos. Mantén los ordenes a un conjunto pequeño de columnas indexadas y haz que el orden por defecto coincida con un índice real.

Chequeo rápido:

  • Si puedes desplazarte indefinidamente sin cargar, probablemente renderizaste demasiado.
  • Si escribir en búsqueda se siente lento, tu consulta probablemente esté escaneando.
  • Si la API de lista devuelve un JSON enorme, estás sobretrayendo datos.
  • Si exportar bloquea la página, el trabajo está ocurriendo en el lugar equivocado.
  • Si cada orden es lento, hay que ajustar índices y opciones de orden.

Lista de verificación rápida y próximos pasos

Trata el rendimiento de listas como una característica de producto, no como un ajuste puntual. Una pantalla de lista es rápida solo cuando se siente rápida mientras personas reales se desplazan, filtran y ordenan con datos reales.

Usa esta checklist para confirmar que arreglaste lo correcto:

  • La primera pintura es rápida: la página carga un payload pequeño y muestra las primeras filas de inmediato.
  • El desplazamiento se mantiene suave: la virtualización está activa, la CPU del navegador no se dispara y las alturas de fila son previsibles.
  • Los filtros se sienten responsivos: escribir o seleccionar un filtro actualiza rápido, y los filtros no se reinician al paginar o refrescar.
  • El orden es sensato: solo permite órdenes con índice o campo precomputado y mantiene el orden consistente entre páginas.
  • Las peticiones están modeladas: la API devuelve solo las columnas que muestras, más IDs y cursores estables, no objetos completos por si acaso.

Una comprobación simple: abre la lista, desplázate durante 10 segundos y luego aplica un filtro común (por ejemplo Estado: Abierto). Si la UI se congela, el problema suele ser renderizado (demasiadas filas DOM) o una transformación pesada del lado cliente (ordenar, agrupar, formatear) ocurriendo en cada actualización.

Próximos pasos, en orden, para no saltar entre arreglos:

  1. Mide un flujo de usuario de extremo a extremo (cargar, desplazarse, filtrar, ordenar) y escribe tiempos objetivo.
  2. Activa virtualización y limita el formateo caro en celdas (fechas, moneda, avatares).
  3. Mueve filtrado y orden al servidor y limita las opciones a las que pueden ser rápidas.
  4. Ajusta consultas y payloads, luego vuelve a medir.

Si construyes esto con Koder.ai (koder.ai), empieza en Planning Mode: define columnas exactas de la lista, campos de filtro y la forma de la respuesta primero. Luego itera usando snapshots y revierte cuando un experimento ralentice la pantalla.

Preguntas frecuentes

¿Por qué mi página de lista se siente bien al principio pero se vuelve lenta al llegar a 100k filas?

Cambia el objetivo de “cargarlo todo” a “mostrar las primeras filas útiles rápido”. Optimiza para el tiempo hasta la primera fila y para que las interacciones (filtrar, ordenar, desplazarse) sean fluidas, incluso si nunca se cargan las 100k filas completas.

¿Cuáles son las métricas más útiles para rastrear en una pantalla de lista lenta?

Mide el tiempo hasta la primera fila tras cargar o cambiar un filtro, el tiempo para que filtros/orden muestren resultados, el tamaño de la respuesta, consultas lentas en la base (especialmente selects amplios y COUNT(*)) y picos en el hilo principal del navegador. Esos números coinciden con lo que los usuarios perciben como “lag”.

¿Cómo puedo saber rápido si la lentitud es frontend o backend?

Limita temporalmente la API para que devuelva solo 20 filas con los mismos filtros y orden. Si va rápido, el coste está en la consulta o el tamaño de la respuesta; si sigue lento, el cuello de botella suele ser el render, el formateo o el trabajo por fila en el cliente.

¿Cuáles son los cambios frontend más fáciles que aceleran tablas grandes?

No renderices miles de filas en el DOM a la vez, mantén simples los componentes de fila y prefiere alturas de fila fijas. Además, evita hacer formateos caros para filas fuera de pantalla; calcula y cachea formateos solo cuando la fila sea visible o esté abierta.

¿Cuándo debería usar virtualización y qué puede romper al añadirla?

La virtualización mantiene montadas solo las filas visibles (más un pequeño buffer) y reutiliza elementos DOM al desplazarse. Vale la pena cuando los usuarios se desplazan mucho o las filas son “pesadas”, pero funciona mejor con altura de fila constante y un diseño de tabla predecible.

¿La paginación es mejor que el scroll infinito para conjuntos de datos grandes?

La paginación suele ser la opción más segura para flujos administrativos porque mantiene a los usuarios orientados y limita el trabajo del servidor. El scroll infinito puede funcionar para navegación casual, pero complica la navegación y el uso de memoria a menos que gestiones el estado y los límites con cuidado.

¿Debo usar paginación por offset o por cursor (keyset)?

La paginación por offset es más simple (page=10&size=50) pero puede volverse lenta en páginas profundas porque la BD tiene que saltarse muchas filas. La paginación por keyset (cursor) suele mantenerse rápida porque continúa desde el último registro visto y evita el coste de saltarse filas.

¿Cómo hago que la búsqueda y los filtros se sientan instantáneos sin sobrecargar el servidor?

No dispares una petición en cada pulsación. Debouncea la búsqueda, cancela solicitudes en curso cuando llega una nueva y por defecto usa filtros que reduzcan los resultados (por ejemplo: últimos 7 días, Mis elementos) para que la primera consulta sea pequeña y útil.

¿Qué debería devolver mi API de lista para que siga siendo rápida?

Devuelve solo los campos que la lista realmente muestra: id, etiqueta, estado, propietario y timestamps suelen ser suficientes. Mueve textos largos, blobs JSON y datos relacionados a una petición de detalle para que la primera pintura sea ligera y predecible.

¿Qué cambios en la base de datos suelen ayudar más con una lista de 100k filas?

Haz que el filtro por defecto y el orden reflejen el uso real, y añade índices que soporten exactamente ese patrón (a menudo índices compuestos). Trata el total exacto como opcional: cachea recuentos, pré-calcula o muestra aproximaciones para no bloquear la respuesta principal.

Related posts