Man öffnet elido.me/abc123 und irgendetwas muss diesen kurzen String in eine vollständige Webadresse umwandeln, bevor der Browser überhaupt etwas laden kann. Der Mechanismus ist einfacher als die meisten annehmen. Ein URL-Shortener speichert ein Mapping von einem Kurzcode zu einer langen Ziel-URL. Wenn man auf den Kurzlink klickt, behandelt der Dienst den Code als Lookup-Key, findet das Ziel und gibt einen HTTP-Redirect zurück, der dem Browser sagt, wohin er tatsächlich gehen soll. Ein Request rein, ein Redirect raus.
Das ist die ganze Idee. Alles andere ist Ingenieursarbeit rund um drei Anforderungen: das Lookup schnell machen, Codes kurz und eindeutig halten, und den Klick aufzeichnen, ohne jemanden zu verlangsamen. Dieser Beitrag erklärt, wie URL-Shortener von Anfang bis Ende funktionieren - mit Elidos Edge-Architektur als konkretem Beispiel, während die Erklärung allgemein für Shortener gilt. Wir behandeln das Slug-zu-URL-Mapping, wie Kurzcodes generiert werden, wo die Daten liegen, die Wahl zwischen 301 und 302, die mehr Leute verwirrt als alles andere, wie ein HTTP-Redirect auf der Leitung aussieht, warum Caching am Edge wichtig ist und wie ein Klick asynchron gezählt wird.
Wie URL-Shortener funktionieren: das Mapping im Mittelpunkt#
Zieht man die Infrastruktur ab, ist ein URL-Shortener ein Key-Value-Store mit einem angehängten Redirect-Handler. Der Key ist der Slug, der Kurzcode nach der Domain. Der Value ist das Ziel, die lange URL, die man ursprünglich eingefügt hat.
Wenn man einen Kurzlink erstellt, schreibt der Shortener eine Zeile: Dieser Slug zeigt auf dieses Ziel. Wenn jemand den Kurzlink besucht, liest der Shortener diese Zeile zurück und handelt danach. Links zu erstellen ist selten; sie zu lesen ist konstant. Ein einzelner Marketing-Link wird vielleicht einmal geschrieben und dann im Laufe seines Lebens einige hunderttausend Mal gelesen. Dieses leselastige Verhältnis ist die wichtigste Tatsache über die Arbeitslast - und es prägt jede daraus folgende Designentscheidung, insbesondere beim Caching.
Das Mapping selbst kann mehr als ein Ziel tragen. In Elido kann ein Slug Targeting-Regeln enthalten, sodass ein Kurzlink je nach Land, Gerät, Sprache oder Uhrzeit auf unterschiedliche Ziele routet. Das nennen wir einen Smart Link - es ist noch immer dasselbe Lookup, nur mit einer kleinen Regelauswertung nach dem Lesen. Die Kernbeziehung ändert sich nie: Slug rein, Ziel raus.
Den Kurzcode generieren#
Wenn der Slug der Key ist - woher kommt er? Es gibt zwei bewährte Ansätze, und die meisten Shortener verwenden einen oder eine Mischung aus beiden.
Der erste ist Base62-Kodierung einer Datenbank-ID. Jeder neue Link erhält eine automatisch hochzählende Integer-ID aus der Datenbank. Man kodiert diesen Integer in Base62, das die 62 URL-sicheren Zeichen a-z, A-Z und 0-9 verwendet. ID 1 wird zu b, ID 125 zu einem zweistelligen Code, und so weiter. Base62 ist dicht: Drei Zeichen decken etwa 238.000 Links ab, fünf Zeichen ca. 916 Millionen, sechs ca. 56 Milliarden. Codes bleiben kurz und kollidieren nie, da sie eins-zu-eins auf eindeutige IDs abgebildet werden. Der Nachteil ist, dass sequenzielle IDs erratbar sind, weshalb viele Systeme den ID-Raum vor der Kodierung mischen oder verschieben.
Der zweite Ansatz ist zufällige Generierung. Man wählt einen zufälligen String fixer Länge aus demselben Alphabet und prüft die Datenbank, ob er nicht bereits vergeben ist. Bei einer Kollision generiert man einen neuen. Kollisionen sind bei vernünftiger Länge verschwindend selten, sodass die Wiederholungsschleife fast nie läuft. Zufällige Slugs sind nicht aufzählbar - das ist das Sicherheitsargument für sie.
Benutzerdefinierte Slugs, die gebrandeten wie elido.me/spring-sale, liegen über beiden Ansätzen. Der Nutzer gibt den String vor; der Shortener prüft ihn auf erlaubte Zeichen und auf Eindeutigkeit gegen denselben Index, bevor er gespeichert wird. Ob der Slug generiert oder von Hand gewählt wurde - er landet an derselben Stelle: einer eindeutigen Spalte im Datenspeicher.
Wo die Daten liegen#
Das Slug-zu-Ziel-Mapping braucht einen Ort, der die Frage "Worauf zeigt dieser Slug?" schnell und konsistent beantworten kann. Als Quelle der Wahrheit ist das fast immer eine relationale Datenbank. Elido verwendet Postgres, mit dem Slug als eindeutig indizierter Spalte, sodass ein Lookup ein einzelner Key-basierter Lesevorgang und kein Table-Scan ist. Postgres hält den kanonischen Datensatz für jeden Link, Nutzer und Workspace.
Bei jedem einzelnen Klick Postgres zu treffen wäre jedoch angesichts des leselastigen Verhältnisses verschwenderisch. Ein Key-basierter Slug-Lookup in Postgres dauert typischerweise ein bis drei Millisekunden - das klingt schnell, bis man es mit dem Klickvolumen eines viralen Links multipliziert und bedenkt, dass eine Datenbankverbindung eine begrenzte Ressource ist. Daher schalten Produktions-Shortener einen Cache vor die Datenbank. Der Cache bedient die meisten Lesevorgänge tatsächlich; die Datenbank ist der Fallback für alles, was der Cache noch nicht kennt.
Elido betreibt einen zweistufigen Cache vor Postgres. Die erste Stufe ist ein In-Process-LRU-Cache im Redirect-Binary selbst, der ein Ziel in wenigen hundert Nanosekunden ohne Netzwerkhop zurückgibt. Die zweite Stufe ist ein Redis-Cluster in derselben Region, der in unter einer Millisekunde antwortet. Nur ein Cold-Miss - ein Slug, den keine der beiden Stufen kürzlich gesehen hat - fällt auf einen Origin-gRPC-Aufruf gegen api-core durch, der Postgres liest. Die kombinierte Trefferrate beider Cache-Stufen liegt bei etwa 99,4%, sodass die Datenbank bei ungefähr einem von 167 Requests berührt wird. Die vollständige Erläuterung, wie sich dieser Cache verhält - einschließlich seiner Eviction-Policy und der aufgetretenen Fehlerszenarien - findet sich in unserem Cache-Strategie-Beitrag.
Was ein HTTP-Redirect tatsächlich ist#
Sobald der Shortener das Ziel hat, muss er es an den Browser zurückgeben. Er tut das mit einem HTTP-Redirect - einer spezifischen Art von Antwort. Statt Seiteninhalt mit einem 200 OK zurückzugeben, sendet der Server einen 3xx-Statuscode und einen Location-Header mit der echten URL. Auf der Leitung sieht die Antwort so aus:
HTTP/1.1 302 Found
Location: https://shop.example.com/spring-collection
Content-Length: 0
Der Browser liest den Statuscode, sieht einen Location-Header und stellt sofort eine neue Anfrage an diese Adresse. Für die klickende Person sieht es wie eine einzelne Navigation aus; unter der Haube sind es zwei Requests, mit dem Kurzlink als schnellem Verzeichnis-Lookup dazwischen. Die Semantik jedes 3xx-Codes ist in RFC 7231 definiert, und Mozillas Leitfaden zu HTTP-Redirects ist die klarste praktische Referenz dafür, was welcher Code tut.
Der Body ist leer, weil nichts zu rendern ist. Die gesamte Nutzlast besteht aus der Statuszeile und dem Header. Das ist ein Teil des Grundes, warum Redirects günstig zu bedienen sind: Es gibt kein Template, keinen Datenbankjoin für Inhalte, kein Markup. Slug auflösen, einen Header setzen, senden.
301 vs. 302: die Wahl, die die Analytics entscheidet#
Hier treffen Shortener im Stillen eine Entscheidung, die die meisten Nutzer nie sehen, die aber bestimmt, ob ihr Link bearbeitbar und trackbar ist. Der Redirect-Statuscode ist keine Formalität. Die beiden gängigen Optionen verhalten sich sehr unterschiedlich.
Ein 301 Moved Permanently teilt dem Browser und jedem Proxy und CDN zwischen Browser und Server mit, dass dieser Kurzlink immer auf dasselbe Ziel zeigen wird. Also cachen sie ihn. Ein 301 wird aggressiv gespeichert. Das nächste Mal, wenn der Besucher auf diesen Kurzlink klickt, könnte sein Browser ihn aus dem Cache auflösen und den Shortener gar nicht kontaktieren. Das ist gut, um einen Round-Trip einzusparen - und eine Katastrophe für ein Link-Tool, weil zwei Dinge kaputtgehen. Erstens werden die Analytics blind: Klicks aus dem Browser-Cache erreichen den Server nie, also werden sie nie gezählt. Zweitens ist das Ziel praktisch eingefroren. Ändert man, wohin der Link zeigt, landen alle, die den 301 bereits gecacht haben, weiterhin auf der alten Adresse, bis ihr Cache abläuft - und das kann man nicht kontrollieren.
Ein 302 Found (und sein strengerer Vetter 307 Temporary Redirect) teilt dem Browser mit, dass dies vorübergehend ist: Beim nächsten Mal wieder anfragen. Der Browser cached das Mapping nicht, sodass jeder Klick den Kurzlink erneut beim Server anfragt. Dieser zusätzliche Round-Trip ist genau das, was ein Link-Tool möchte. Jeder Klick erreicht die Infrastruktur, sodass jeder Klick zählbar ist - und weil der Server das Ziel jedes Mal frisch auflöst, kann man ändern, wohin ein Link zeigt, und die neue Adresse gilt beim nächsten Klick. Der Preis ist ein Netzwerk-Round-Trip pro Klick, den ein gut gebautes Edge auf einstellige Millisekunden hält.
Deshalb setzt Elido standardmäßig auf 302. Bearbeitbare Ziele und genaue Klickdaten sind der Sinn eines verwalteten Links - und ein 301 tauscht beides gegen eine Cache-Optimierung ein, die man meistens nicht möchte. RFC 7231 legt fest, dass ein 301 standardmäßig cachebar ist, während ein 302 nur gespeichert wird, wenn Header das explizit sagen - genau das Verhalten, das die beiden Anwendungsfälle verlangen. Es gibt enge Fälle, in denen ein permanenter Redirect korrekt ist, etwa bei einer echten Domain-Migration, aber für trackbare, bearbeitbare Kurzlinks ist der temporäre Redirect der richtige Standard.
Caching am Edge für niedrige Latenz#
Ein Redirect ist synchron und blockierend. Der Browser des Besuchers wartet beim Kurzlink, bis der Redirect ankommt, und erst dann kann er die Seite laden, auf die es ankommt. Jede Millisekunde beim Auflösen des Slugs ist eine Millisekunde Wartezeit des Besuchers mehr. Deshalb schieben ernsthafte Shortener das Lookup so nah wie möglich an den Besucher.
Elido betreibt den Redirect-Handler an Edge-Points-of-Presence in Frankfurt, Ashburn und Singapur, mit Traffic-Routing zum nächsten POP. Der Handler ist in Go auf Basis von fasthttp geschrieben - gewählt, weil sein Allocation-freier Request-Pfad Garbage-Collection-Pausen unter anhaltender Last vorhersehbar hält. Kombiniert mit dem In-Memory-Cache hält das Redirects auf ein p95 unter 15ms bei einem Cache-Hit, gemessen am POP: ca. 4,8ms Median in Frankfurt, bis zu ca. 14ms p95 in Singapur, wo die Geografie weiter ist. Der Großteil dieses Budgets ist physischer Netzwerktransit - der unvermeidliche Abstand zwischen Besucher und nächstem POP, den man softwareseitig nicht wegoptimieren kann. Das vollständige Latenzbudget und wie jede Region misst, haben wir in dem p95-unter-15ms-Beitrag dokumentiert.
Das Lookup am Edge statt auf einem einzelnen zentralen Server zu betreiben ist der Unterschied zwischen einem Redirect, der sich sofort anfühlt, und einem, der eine sichtbare Verzögerung hinzufügt. Es ist auch der Grund, warum Anycast-Edge-Routing ein DNS-only-Setup für diese Arbeitslast schlägt - einen Vergleich, den wir in Edge-POPs versus DNS-only-Routing eingehen. Die Kurzversion: Das Netzwerk erledigt die Geografie, und der Cache erledigt die Geschwindigkeit.
Den Klick zählen, ohne den Redirect zu verlangsamen#
Ein Shortener, der nur weiterleitet, wäre ein Redirect-Dienst. Was ihn zu einem Link-Management-Tool macht, ist, dass er jeden Klick zählt und sagt, wer geklickt hat, woher, mit welchem Gerät. Das Schwierige daran: das zu tun, ohne den Besucher warten zu lassen.
Die Antwort ist, beide vollständig zu entkoppeln. Wenn der Redirect-Handler einen Slug auflöst, sendet er sofort die 302-Antwort. Die Aufzeichnung des Klicks erfolgt danach, als Fire-and-Forget-Arbeit. Der Handler hängt ein Klick-Event - Slug, Zeitstempel, eine gekürzte IP, einen User-Agent-Hash - in eine Message Queue und macht weiter. Er wartet nicht auf die Bestätigung des Schreibvorgangs. Wenn die Queue kurzzeitig nicht verfügbar ist, wird der Klick verworfen, statt den Redirect zu verzögern. Wir haben bewusst entschieden, dass das Verlieren eines Klicks bei einem Infrastrukturausfall akzeptabel ist - das Fehlschlagen eines Redirects jedoch nicht.
Elido verwendet Redpanda als diese Queue. Ein separater Consumer, der Click-Ingester, liest Events von der Queue und schreibt sie in ClickHouse - eine spaltenorientierte Datenbank, die für die hochvolumige Append-and-Aggregate-Arbeitslast gebaut ist, die Click-Analytics darstellt. Der Redirect des Besuchers wurde bereits Millisekunden zuvor abgeschlossen; die Analytics-Zeile landet einige Sekunden später, vollständig außerhalb des Hot-Paths. Das Queue-Design erklären wir in Fire-and-Forget-Click-Ingestion und warum ein Columnar-Store Postgres für diesen Zweck schlägt in Warum wir ClickHouse für Click-Analytics verwenden.
Diese Entkopplung ist der Grund, warum die Analytics detailliert sein können, ohne langsam zu sein. Der Redirect-Pfad bleibt schlank, weil kein Zählen, Bewerten oder Aggregieren stattfindet, während der Besucher wartet.
Alles zusammen#
Ein URL-Shortener, von Anfang bis Ende, ist eine kurze Sequenz. Man erstellt einen Link, und der Shortener speichert ein Slug-zu-Ziel-Mapping in Postgres, wobei der Slug als eindeutiger Key generiert oder validiert wird. Ein Besucher klickt, die Anfrage landet am nächsten Edge-POP, und der Handler löst den Slug aus einem In-Memory-Cache auf - er fällt nur bei einem Miss auf Redis und dann die Datenbank durch. Er gibt einen 302 mit dem Ziel im Location-Header zurück, sodass der Klick zählbar und das Ziel bearbeitbar bleibt. Dann sendet er das Klick-Event an eine Queue, damit ein separater Consumer es speichert - ohne jemanden warten zu lassen.
Jedes Teil ist für sich einfach. Die Ingenieursarbeit steckt in den Verhältnissen und Budgets: eine leselastige Arbeitslast, die einen Cache will, eine Latenzgrenze, die den Edge will, und eine Analytics-Anforderung, die außerhalb des Hot-Paths bleiben soll. Wer direkt darauf aufbauen möchte, findet in der Smart-Links-Funktion die Regelschicht, in der API und SDKs die Möglichkeit, Links aus Code heraus zu erstellen, und auf der Entwickler-Seite sowie in den Edge-Redirect-Architekturdocs tiefere Einblicke in die Einzelteile. Wer ein Tool abwägt statt eines zu bauen, findet in den Beiträgen über Was ein URL-Shortener ist und Ob URL-Shortener sicher sind den nutzerorientierte Blickwinkel, und die Preisseite zeigt, wo der kostenlose Tarif endet.