Cursor u offset para un listado de infracciones que cambia
El offset habilita saltos y totales; el cursor, atado a un corte, habilita un recorrido sin repetidos ni omitidos. La elección depende de si la colección cambia mientras se la lee y de hasta dónde pagina el consumidor.
Un listado de infracciones de flota no se queda quieto mientras alguien lo lee. Entre la primera página y la última pueden entrar actas nuevas, corregirse importes y retirarse registros. La pregunta operativa no es cuál forma de paginar es superior, sino qué garantía necesita quien consume ese listado.
Conviene separar dos cosas que suelen viajar juntas: cómo se pide la página siguiente y qué promete el servidor sobre el conjunto que se recorre. La primera es un parámetro; la segunda es un contrato.
Qué promete cada forma
Con offset el cliente pide una posición numérica dentro de un orden: salteá cincuenta actas y traeme las veinte siguientes. Esa posición se recalcula en cada pedido sobre el estado del momento: si la colección cambió, el índice cincuenta ya no marca el mismo borde.
Con cursor el cliente no pide una posición sino una continuación: seguí después de este punto. El servidor entrega un valor opaco y el cliente lo devuelve sin interpretarlo. RFC 8977, que estandariza parámetros de orden y paginado para RDAP, trata el cursor de esa manera: un dato que produce el servidor, no una coordenada del cliente.
La diferencia recién se nota cuando el recorrido dura más que un cambio: en un listado de infracciones, más que la carga de un acta nueva.
Lo que se pierde al pasar de offset a cursor
Migrar no es una mejora transparente. Un paginado numérico permite:
- saltar a una página arbitraria sin recorrer las anteriores;
- mostrar “página 4 de 12” cuando el total se conoce;
- retroceder con la misma aritmética con la que se avanzó;
- reanudar con un número que el cliente calcula solo, sin depender de un valor emitido por el servidor.
Un cursor secuencial no ofrece ninguna de las cuatro, por diseño. RFC 8288 define los enlaces tipados y su serialización en el encabezado Link, y ahí se ve la asimetría: un recorrido por cursor publica next sin esfuerzo, mientras que prev o last sólo corresponden si el servidor puede sostener esos enlaces. Prometer un total sobre una colección viva es prometer un número que se mueve; RFC 8977 lo trata como un parámetro que el cliente pide aparte, no como un subproducto del recorrido.
Si el panel de flota que consume el listado de multas tiene un paginador numerado, cambiar de estrategia es un cambio de producto, no una optimización interna.
Cuándo alcanza el offset y cuándo no
El offset no es un error histórico. Alcanza cuando el conjunto no cambia durante la lectura, o cuando la lectura es tan corta que un cambio resulta improbable y sus consecuencias, tolerables: un informe de infracciones ya cerrado, una pantalla que alguien mira una vez. Tampoco conviene rediseñar por un costo que nadie paga: para servir un offset profundo el motor suele recorrer y descartar las filas previas, pero eso pesa sólo si alguien pagina hondo de verdad.
El cursor se vuelve necesario cuando el consumidor recorre el conjunto entero y ese recorrido tiene que ser auditable: el barrido nocturno de las patentes de la flota, la exportación completa de actas. Ahí una fila repetida u omitida no es una molestia visual: es un acta que se paga dos veces o que nunca llega al descargo.
Con un matiz: el cursor por sí solo no congela nada. Si sólo codifica el último identificador entregado, las páginas siguientes se leen igual sobre la colección viva. La garantía aparece cuando queda atado a un corte —una revisión, una instantánea— con su costo de retención; el diseño está en cursores estables para paginar resultados que cambian.
También hace falta un orden total: ordenar sólo por fecha de infracción permite empates, y dos actas del mismo operativo pueden intercambiar posición entre pedidos. Sin un segundo criterio estable, ninguna de las dos estrategias es reproducible.
Convivir con las dos sin romper clientes
Las dos pueden coexistir si el contrato dice qué garantiza cada una. Un camino intermedio es aceptar offset dentro de un corte declarado: se conservan el salto y el total a cambio de mantener esa revisión disponible por un tiempo acotado. Otro es fijar un tope de profundidad y, al superarlo, responder un error legible en vez de servir en silencio una página cara e inconsistente. RFC 9457 define un formato de error legible por máquina, con un identificador de tipo que permite distinguir “offset máximo excedido” de “cursor vencido” sin deducirlo de un texto.
Si la variante vieja se retira, conviene anunciarlo con anticipación: RFC 9745 define el campo de respuesta Deprecation para avisar que un recurso quedará o ya quedó obsoleto, y prevé un enlace con relación deprecation hacia la documentación del cambio. Un mismo recorrido, eso sí, no debería cambiar de estrategia a mitad de camino.
Qué verificar antes de elegir
Antes de escribir el parámetro, respondé cuatro preguntas: si la colección puede cambiar mientras se la recorre; si el consumidor salta a páginas arbitrarias o recorre todo; hasta qué profundidad se pagina de verdad; y si hay un orden total sobre columnas estables.
Con esas respuestas la decisión deja de ser de gusto. Un listado corto de actas tolera offset; el barrido completo de una flota, no. Y cualquiera sea la elección, el contrato debería explicar qué promete el recorrido, no sólo cómo se pide la página siguiente.
Metodología
- Alcance
- Criterios para elegir entre paginado por offset y paginado por cursor en un listado de infracciones que puede cambiar durante la lectura. No cubre el diseño interno del cursor ni la elección de índices de un motor de base de datos concreto.
- Unidad de análisis
- Un recorrido completo del listado, identificado por su orden, su tamaño de página y la estrategia de continuación usada.
- Cobertura
- Semántica de enlaces, parámetros estandarizados de paginado, formato de errores y anuncio de obsolescencia según RFC 8288, RFC 8977, RFC 9457 y RFC 9745, revisados al 29 de agosto de 2026.
Limitaciones
- Los estándares citados no imponen una estrategia de paginado ni un tope de profundidad: fijarlos es una decisión de cada contrato.
- El costo de un offset profundo depende del motor, los índices y el volumen; conviene medirlo sobre la infraestructura propia antes de rediseñar.
- La nota compara formas de continuar un recorrido; la consistencia efectiva depende además de que exista un corte declarado y un orden total.
Fuentes
- RFC 8977 — RDAP sorting and paging parameters — RFC Editor (consultada el )
- RFC 8288 — Web Linking — RFC Editor (consultada el )
- RFC 9457 — Problem Details for HTTP APIs — RFC Editor (consultada el )
- RFC 9745 — Deprecation HTTP Response Header Field — RFC Editor (consultada el )
Preguntas frecuentes
¿El cursor es siempre mejor que el offset?
No. Es mejor para recorrer entero un conjunto que cambia, pero pierde algo que el offset da gratis: saltar a una página arbitraria, retroceder de forma simétrica y sostener un “página 4 de 12”. Si el consumidor necesita eso, migrar no es una optimización sino un cambio de producto.
¿Cómo me doy cuenta de si el offset me está repitiendo u omitiendo filas?
Comparando el recorrido contra sí mismo: contá los identificadores únicos que trajo una lectura completa y confrontá ese conjunto con los registros que existían al inicio dentro del mismo filtro. Si aparecen duplicados, o falta alguno que no cambió de estado, el problema no es del cliente: la posición numérica se recalculó sobre otra versión de la colección.
¿Por qué un offset alto se vuelve caro?
Porque para entregar la página el motor suele tener que recorrer y descartar las filas previas, y ese trabajo tiende a crecer con la profundidad. Un cursor apoyado en las columnas de orden puede resolverse con un índice. Cuánto pesa en la práctica depende del motor y del volumen, así que conviene medirlo antes de rediseñar.
¿Se pueden ofrecer las dos formas en la misma API?
Sí, si el contrato es explícito sobre qué garantiza cada una y un mismo recorrido no cambia de estrategia a mitad de camino. Si una variante se retira, conviene anunciar la obsolescencia y documentar cómo migrar antes de quitarla.
Notas relacionadas
Cursores estables para paginar resultados que pueden cambiar mientras se leen
Si una colección cambia entre la primera y la última página, el offset puede repetir u omitir resultados. Un cursor ligado a una revisión conserva un corte auditable.
Consultar mil patentes por día: cómo se dimensiona una integración
Mil patentes por día no equivalen a mil solicitudes: cada dominio puede requerir varias jurisdicciones, reintentos y reconsultas. Dimensionar es convertir ese volumen en un presupuesto verificable.
Tests de contrato de la API de multas: cambios incompatibles
Un campo opcional nuevo suele ser compatible; un enum cerrado nuevo puede romper un cliente estricto. Los fixtures de consumidor convierten esas diferencias en pruebas antes del despliegue.