Paginación en SQLAlchemy con limit, offset y Cursor resuelve un problema frecuente en proyectos Python: Devuelve páginas previsibles sin repetir ni omitir filas. Esta guía explica el mecanismo, presenta un ejemplo ejecutable y marca los límites que evitan una implementación frágil.

Concepto y caso de uso

Offset es sencillo para resultados pequeños; el cursor usa la última clave ordenada y escala mejor en tablas grandes.

Para repasar los fundamentos relacionados, consulta también la guía de SQLAlchemy. La integración es más simple cuando cada función recibe dependencias y datos explícitamente en lugar de depender de estado global.

Ejemplo práctico

stmt = select(Post).where(Post.published.is_(True)).order_by(Post.created_at.desc(), Post.id.desc()).limit(21)
rows = session.scalars(stmt).all()
has_next = len(rows) > 20
items = rows[:20]

Toda paginación requiere un orden total y estable, normalmente con la clave primaria como desempate.

Decisiones importantes

La elección correcta depende del contrato público, del volumen y del comportamiento ante fallos.

Considera concurrencia, entradas vacías y fallos parciales. Documenta cada límite que afecte a consumidores y usa nombres que expresen intención.

Errores frecuentes

El ejemplo mínimo no sustituye límites, manejo de errores y observabilidad. Sin order_by el orden no está garantizado. Un offset alto recorre muchas filas y las escrituras concurrentes desplazan resultados.

Evita capturar excepciones sin contexto o devolver resultados parciales como si fueran completos. Un fallo explícito suele ser más seguro que datos silenciosamente incorrectos.

Cómo validar

Valida el comportamiento y no solo el camino feliz. Prueba empates, última página, inserciones entre peticiones y el límite máximo aceptado por la API.

La documentación oficial, consultada el 28 de julio de 2026, detalla la API y debe ser la referencia para cambios futuros.