Was ist API-Pagination? Cursor vs. Offset im Vergleich
API-Pagination teilt große Ergebnismengen in Seiten. Offset, Seitenzahl, Cursor und Keyset im Vergleich, mit SQL-Beispielen, Link-Header, Fallstricken.
Was ist API-Pagination?
Bei der API-Pagination liefert eine API eine große Ergebnismenge in kleinen Teilen, den Seiten, über mehrere Anfragen. Statt einer Antwort mit einer Million Datensätze fragt der Client jeweils 50 oder 100 an und holt den nächsten Teil, wenn er ihn braucht. Das schont Datenbank, Speicher und Netzwerk und hält die Antwortzeiten vorhersagbar.
Die gewählte Strategie beeinflusst Geschwindigkeit, Korrektheit und die Möglichkeiten des Clients. Offset-Pagination ist am einfachsten, Cursor- und Keyset-Pagination halten bei großen oder sich ändernden Daten besser durch. Eine schlechte Wahl ist ein häufiger Grund, warum ein Endpunkt mit wachsenden Daten langsamer wird.
Die wichtigsten Pagination-Strategien
| Strategie | Form der Anfrage | Geeignet für |
|---|---|---|
| Offset und Limit | ?offset=200&limit=50 | Kleine Datenmengen, Sprung auf eine Seite |
| Seitennummer | ?page=5&per_page=50 | Wie Offset mit freundlicherer URL |
| Cursor | ?cursor=abc123&limit=50 | Feeds, Endlos-Scrollen, sich ändernde Daten |
| Keyset (Seek) | ?after_id=12345&limit=50 | Große Datenmengen mit stabiler Sortierung |
Offset und Limit
Der Client gibt an, wie viele Zeilen übersprungen und wie viele geliefert werden sollen.
SELECT * FROM users
ORDER BY created_at, id
LIMIT 50 OFFSET 200;Vorteile: einfach zu bauen, erlaubt den Sprung auf Seite 7, macht eine Gesamtzahl leicht. Nachteile: Die Datenbank muss trotzdem an allen übersprungenen Zeilen vorbei, tiefe Seiten werden langsam. Werden zwischen Anfragen Zeilen eingefügt oder gelöscht, erscheinen Einträge doppelt oder fehlen.
Cursor-basierte Pagination
Der Server liefert ein opakes Token, das markiert, wo die letzte Seite endete, und der Client schickt es für die nächste Seite zurück.
GET /api/users?cursor=eyJpZCI6MTIzNDV9&limit=50
{
"data": [ ... ],
"next_cursor": "eyJpZCI6MTIzOTV9",
"has_more": true
}Ein Cursor ist oft ein Base64-kodierter Sortierschlüssel wie {"id": 12345}. Vorteile: stabil bei Datenänderungen, schnell bei indiziertem Sortierschlüssel, ideal für Endlos-Scrollen. Nachteile: kein Sprung auf eine beliebige Seite, und eine Gesamtzahl braucht eine eigene Abfrage.
Keyset-Pagination (Seek)
Keyset-Pagination ist das, was ein Cursor meist im Hintergrund tut: Die Abfrage filtert auf den zuletzt gesehenen Wert, statt Zeilen zu überspringen.
SELECT * FROM users
WHERE id > 12345
ORDER BY id
LIMIT 50;Bei zusammengesetzter Sortierung vergleichen Sie die Spalten gemeinsam. Datenbanken mit Zeilenvergleich, etwa PostgreSQL, akzeptieren Folgendes:
SELECT * FROM users
WHERE (created_at, id) > ('2026-01-15', 12345)
ORDER BY created_at, id
LIMIT 50;Mit einem Index auf den Sortierspalten springt die Datenbank direkt zum Startpunkt, Seite 1.000 kostet also ungefähr so viel wie Seite 1.
Warum tiefe Offsets langsam werden
Bei einer Seitengröße von 50 muss die Datenbank die übersprungenen Zeilen durchlaufen, bevor sie die gewünschten 50 liefert. Die Tabelle zeigt diesen Aufwand für eine Offset- gegenüber einer Keyset-Abfrage. Es ist einfache Rechnung, kein Benchmark, und echte Zeiten hängen von Indizes und Datenbank ab.
| Seite | Zu durchlaufende plus gelieferte Zeilen (Offset) | Zu durchlaufende plus gelieferte Zeilen (Keyset) |
|---|---|---|
| 1 | 50 | 50 |
| 10 | 500 | 50 |
| 100 | 5.000 | 50 |
| 1.000 | 50.000 | 50 |
| 10.000 | 500.000 | 50 |
Wie Clients die nächste Seite finden
Es gibt zwei verbreitete Muster. Das erste legt die Navigation in den Link-Header, definiert in RFC 8288 (Web Linking, löst RFC 5988 ab):
Link: <https://api.example.com/users?page=3&per_page=50>; rel="next",
<https://api.example.com/users?page=1&per_page=50>; rel="prev"Die REST-API von GitHub arbeitet so, mit den Relationen next, prev, first und last, und begrenzt per_page bei den meisten Endpunkten auf 100. Clients sollten diesen URLs folgen, statt eigene zu bauen. Das zweite Muster legt Metadaten in die Payload der Antwort: ein next_cursor und ein has_more-Flag oder ein pagination-Objekt mit Seite, Seitengröße und Summen. GraphQL-APIs folgen meist dem Relay-Cursor-Connection-Muster mit edges, pageInfo.hasNextPage und endCursor, und die Dokumentation von GraphQL empfiehlt Cursor-Pagination.
Best Practices
- Standard- und Höchstgröße festlegen. Zum Beispiel 25 bis 50 als Standard und eine dokumentierte harte Obergrenze. Alles darüber ablehnen oder kappen.
- Stabile, eindeutige Sortierung nutzen. Die ID als Tiebreaker ergänzen, sonst wiederholen sich Zeilen mit gleichen Werten oder verschwinden zwischen Seiten.
- Sortierspalten indizieren. Sonst ist jede Seite eine komplette Sortierung.
- Bei großen oder wachsenden Tabellen Keyset oder Cursor bevorzugen. Offset bleibt für kleine Admin-Listen.
- Vorsicht bei Gesamtzahlen.
COUNT(*)auf einer großen Tabelle ist langsam. Bieten Sie eine Schätzung oder gar keine an. - Das Schema dokumentieren. Beschreiben Sie in der OpenAPI-Spezifikation, wie die nächste Seite angefordert wird und wann die Liste endet.
- Die erste Seite cachen. Sie wird am häufigsten abgefragt. Siehe API-Caching.
Häufige Pagination-Fehler
- Tiefe Offsets.
offset=100000auf einer großen Tabelle ist die klassische langsame Abfrage. - Nicht eindeutige Sortierung. Sortieren nach einer Spalte mit Gleichständen dupliziert oder überspringt Zeilen.
- Keine Höchstgrenze. Ein Client sendet
limit=1000000, und Sie haben sich selbst lahmgelegt. - Interne Cursor offenlegen. Clients fangen an, sie zu parsen, und das Format ist nie mehr änderbar. Halten Sie sie opak.
- Bei jeder Anfrage alles zählen. Die Zähl-Abfrage kann teurer sein als die Seite.
- Das Listenende vergessen. Geben Sie ein klares Signal zurück, etwa
has_more: falseoder einen leerennext_cursor.
Pagination im Performance-Test
Pagination-Fehler zeigen sich meist unter Last, nicht bei einer einzelnen Anfrage. Ein Lasttest, der nur Seite 1 abruft, übersieht die langsamen Abfragen tiefer Seiten, die echte Clients und Crawler auslösen. Nehmen Sie eine Mischung aus Seiten, eine tiefe Worst-Case-Seite und die maximale Seitengröße in Ihre Szenarien auf und beobachten Sie die 95. Perzentile der Antwortzeit statt des Durchschnitts. Danach überwachen Sie diese Endpunkte mit dem API-Monitoring; kostenlose Checks laufen alle 5 Minuten. Starten Sie mit kostenlosen API-Checks. Weiterlesen: API-Performance-Metriken, häufige API-Performance-Probleme und Lasttests für RESTful APIs.
Häufige Fragen: API-Pagination
Soll ich Offset- oder Cursor-Pagination verwenden?
Nutzen Sie Cursor- oder Keyset-Pagination für große Tabellen, Live-Feeds und alles, was Nutzer durchscrollen. Offset oder Seitenzahlen genügen für kleine Listen, bei denen man auf eine Seite springt, etwa eine Admin-Tabelle.
Wie implementiere ich Cursor-Pagination?
Sortieren Sie nach einem indizierten, eindeutigen Schlüssel. Geben Sie den Schlüssel des letzten Eintrags als kodierten Cursor zurück. Bei der nächsten Anfrage dekodieren Sie ihn und fragen die Zeilen nach diesem Schlüssel in derselben Sortierung ab.
Wie liefere ich bei Cursorn eine Gesamtzahl?
Führen Sie eine separate Zähl-Abfrage aus, liefern Sie eine Schätzung oder lassen Sie die Summe weg. Viele Cursor-APIs legen sie bewusst nicht offen, weil exakte Zählungen teuer sind.
Welche Seitengröße soll ich erlauben?
Wählen Sie einen maßvollen Standardwert und ein dokumentiertes Maximum. Üblich sind Maxima um 100, was GitHub bei den meisten Endpunkten verwendet. Größere Seiten bedeuten langsamere, schwerere Antworten.
Gehören Pagination-Parameter in die Query-String oder in den Body?
Bei GET-Anfragen in den Query-String, weil das üblich und cachebar ist. Ein Body ist bei POST-basierten Suchen mit komplexen Filtern akzeptabel.
Brauche ich Cursor für vorwärts und rückwärts?
Für die meisten Feeds reicht nur vorwärts. Vorherige Seiten bedeuten eine umgekehrte Abfrage und zusätzliche Sonderfälle.
Verwandte Begriffe
- Was ist API-Sicherheit?
- Was ist API-Sprawl? Definition, Ursachen und Gegenmaßnahmen
- Was ist API-Threat-Hunting?
- Was ist ein Bearer Token? Definition, JWT und Sicherheit
- Was ist der curl-Befehl? Beispiele, Flags, HTTP-Requests
- Was ist die History-API?
- Was ist Idempotenz? HTTP-Methoden, Idempotency-Keys, Beispiele
- Was ist JSON? Einsteiger-Guide mit Syntax und Beispielen
Verwandte LoadFocus-Tools
Setze dieses Konzept mit LoadFocus in die Praxis um, derselben Plattform, die alles antreibt, was du gerade gelesen hast.