Elido
6 Min. LesezeitEngineering

Bereitstellung der TinyURL-Migration: Pro/Bulk REST, kein Free-Tier-Pfad

Wie wir den Ein-Klick-Import für TinyURL Pro/Bulk für Elido gebaut haben – warum die öffentliche TinyURL-API nicht existiert, die Alias-vs-Slug-Terminologie und das Limit, das wir bewusst gesetzt haben.

Marius Voß
DevRel · edge infra
Pipeline-Diagramm: TinyURL Pro/Bulk API auf der linken Seite fließt durch den Elido-Import-Worker in die Links-Tabelle, mit einem Seitenbereich, der die numerischen Garantien auflistet (50k-Obergrenze, 30-Minuten-Budget, 100 pro Seite, nur Pro/Bulk-Pläne)

Die vierte Migrationsquelle in unserem Tier-3-Rollout wurde heute bereitgestellt. Fügen Sie ein TinyURL Pro oder Bulk API Token ein, wählen Sie eine Elido-Zieldomain und klicken Sie auf Start. Vier bis sieben Minuten später befindet sich jeder TinyURL-Alias auf Ihrer Elido-Domain, wobei der Alias beibehalten wurde, sofern kein Konflikt auftrat.

Dieser Beitrag ist der technische Bericht – was für TinyURL spezifisch ist, das bewusste Limit, das wir eingeführt haben, und warum eine "Free-Tier-TinyURL-Migration" nichts ist, was wir bauen können.

Das Free-Tier-Problem#

Die öffentliche TinyURL hat keine API und hatte noch nie eine. Der klassische tinyurl.com/<slug>, den Sie ohne Konto erstellen, ist ein Fire-and-Forget-Redirect – der Benutzer erstellt ihn über das Formular auf der Homepage, erhält einen Slug zurück und dieser Slug taucht nie wieder in einem Dashboard auf. Es gibt keine Liste pro Benutzer, da es keine Bindung pro Benutzer gibt.

Dies ist hinlänglich bekannt, aber es lohnt sich, dies auf der /migrate-from/tinyurl Landingpage hervorzuheben, da die Suchanfrage "migrate from TinyURL" nicht zwischen Pro und Free unterscheidet. Wir haben Folgendes implementiert:

  • Einen deutlichen "Pro/Bulk only"-Hinweis auf der Hero-Sektion der Landingpage.
  • Einen FAQ-Eintrag, der Free-Tier-Benutzer auf das /docs/guides/bulk-create-Formular für die Bulk-Kürzung einer Liste von Zielen verweist.
  • Einen Token-Validierungsschritt im Launcher, der frühzeitig mit "dieses Token ist nicht in einem Pro- oder Bulk-Plan" fehlschlägt, anstatt den Vorgang mitten in der Paginierung mit einem 401 scheitern zu lassen.

Die Begründung: Jede andere Migrationsquelle, die wir anbieten, hat einen Erfolgs-Pfad für "jeden Benutzer, der danach sucht". TinyURL ist die Ausnahme – Free-Tier-Benutzer benötigen ein anderes mentales Modell und wir sollten diese Erwartung setzen, bevor sie irgendetwas einfügen.

Aufbau der Pro/Bulk REST API#

Die TinyURL Pro API ist unkompliziert: Bearer-Token, JSON-Antworten, 100 Aliase pro Seite. Die Paginierung verwendet einen page-Query-String-Parameter, der 1-indiziert ist; die Antwort enthält data.aliases (das Link-Array) und meta.has_more (das Fortsetzungssignal).

const tinyurlPageSize = 100

page := 1
for {
    resp, err := w.fetchPage(ctx, opts.Token, page)
    if err != nil { /* mark failed */ return }
    if len(resp.Data.Aliases) == 0 { break }
    for _, alias := range resp.Data.Aliases { /* import */ }
    if !resp.Meta.HasMore { break }
    page++
}

Jeder Alias enthält url (das lange Ziel), alias (der benutzerdefinierte Slug oder der automatisch generierte Kurzcode), description (ein optionales TinyURL-Feld, das wir als Elido-Linktitel beibehalten) und eine domain (TinyURL erlaubt gebrandete Domains bei Bulk-Plänen).

Terminologie – Alias vs. Slug#

TinyURL nennt sie "Aliases". Wir nennen sie "Slugs". Dasselbe – die Zeichenfolge nach dem Host in der Redirect-URL. Die Migration behält den Alias 1:1 bei, sofern die Elido-Zieldomain keine Kollision aufweist; bei einer Kollision greift die standardmäßige Suffix/Skip/Fail-Konfliktstrategie.

Wir haben überlegt, "Slug" im Launcher in "Alias" umzubenennen, um der Terminologie des Quellanbieters zu entsprechen, haben dies jedoch aus Gründen der Konsistenz abgelehnt. Jede andere Elido-Oberfläche – Linkliste, API, SDK, Dashboard – verwendet "Slug". Die Einführung einer terminologischen Asymmetrie in einen Launcher würde die Erfahrung nach dem Import verwirrend machen.

Der Launcher zeigt jedoch ein einzeiliges Label "TinyURL nennt diese Aliase" über dem Radio-Button für die Konfliktstrategie an, sodass Benutzer, die auf der Rezeptseite nach "Alias" suchen, das richtige Steuerelement finden, ohne jedes Wort lesen zu müssen.

Gebrandete Domains und DNS-Übergabe#

TinyURL Bulk-Pläne unterstützen gebrandete Domains – Ihr eigener Hostname, der über die Infrastruktur von TinyURL geroutet wird. Wenn Sie zu Elido migrieren, wird der Slug sauber importiert und die DNS-Seite ist eine einfache CNAME-Änderung.

Der interessante Fall ist: "Ich habe eine gebrandete Domain auf TinyURL Bulk und möchte den gleichen Hostnamen nach der Migration behalten". Wir handhaben dies auf die gleiche Weise wie die Short.io-Migration:

  • Die Migration wird abgeschlossen. Importierte Links befinden sich standardmäßig auf s.elido.me/<alias> (oder Ihrer bestehenden Elido-Custom-Domain).
  • Sie fügen die TinyURL-gebrandete Domain als Elido-Custom-Domain über /docs/guides/custom-domains hinzu.
  • Sie zeigen mit dem CNAME auf Elido. Caddys on-demand TLS stellt bei der ersten Anfrage ein Zertifikat aus; domain-manager ist die "Source-of-Truth" für die Allow-List, sodass nicht autorisierte Hostnamen abgelehnt werden.
  • Die Oberfläche von TinyURL löst für diesen Hostnamen nicht mehr auf; die von Elido übernimmt.

Sie können beide Oberflächen parallel aktiv lassen, bis Ihr TinyURL-Abonnement endet, dann ist der Wechsel nur noch das Auslaufenlassen des TinyURL-Hostnamens. Keine Dringlichkeit, kein Risiko am Tag des Wechsels.

Was wir nicht migrieren#

Klick-Historie. Die Analysen von TinyURL Pro/Bulk sind separate Berichts-Endpunkte, die nicht für den Export strukturiert sind. Der Bulk-Plan zeigt Klickzahlen pro Link im Dashboard an, stellt sie aber nicht über die migrationsfreundliche API bereit; neue Klicks landen nach dem Wechsel in den Elido-Analysen.

QR-Styling und Bulk-Tier UTM-Vorlagen. Dasselbe wie bei jeder anderen Migrationsquelle – der Slug wird importiert, die umgebende Präsentationsschicht wird in Elido neu aufgebaut. Getaggt als imported:tinyurl für Bulk-Nachverfolgung über Kampagnen.

Free-Tier-TinyURL-Links. Wie oben diskutiert, hat die öffentliche TinyURL keine API. Die Lösung ist das Bulk-Create-Formular, kein Migrations-Job.

Token-Handling#

Dieselbe One-Shot-Semantik wie bei Bitly, Rebrandly und Short.io:

bgCtx := context.WithoutCancel(r.Context())
go h.tinyurl.Run(bgCtx, job.ID, imports.TinyURLJobOptions{
    Token: req.Token,
})

source_token_id bleibt NULL. Das Token lebt im Prozessspeicher von api-core für den Worker-Durchlauf und wird nach Abschluss gelöscht. Keine Persistenz, keine service_tokens-Zeile, keine ADR-0036 Envelope Encryption – diese sind für Tier-2-Integrationen, bei denen der Benutzer wiederkehrende Anbieteraufrufe wünscht.

Der Token-Validierungsschritt beim Job-Start trifft TinyURLs /account/domains-Endpunkt – ein kostengünstiger Aufruf, der eine Liste von Domains zurückgibt, die das Token sehen kann. Wenn ein 401 zurückgegeben wird, schlagen wir frühzeitig mit "Token ist ungültig oder nicht in einem Pro/Bulk-Plan" fehl, anstatt den Benutzer zwei Minuten auf ein 401 mitten in der Paginierung und eine weniger hilfreiche Fehlermeldung warten zu lassen.

Konfliktlösung#

Identisch mit jedem anderen Migrationsanbieter – Suffix-Walks myalias-2, myalias-3, … bei Kollision; Skip belässt den bestehenden Elido-Link und protokolliert die Quellzeile; Fail bricht beim ersten Konflikt ab.

func (w *TinyURLWorker) resolveSlug(ctx context.Context, domainID int64, desired, strategy string) (string, error) {
    if _, err := w.links.GetByDomainSlug(ctx, domainID, desired); err != nil {
        if errors.Is(err, pgx.ErrNoRows) { return desired, nil }
        return "", fmt.Errorf("slug lookup: %w", err)
    }
    // Suffix/Skip/Fail-Verzweigung identisch mit bitly.go
}

Die Suche ist ein indexierter Lesezugriff pro Zeile. Wir zahlen einen zusätzlichen Lesezugriff, erhalten aber deterministische Suffix-Walks und freundlichere Fehlermeldungen als bei der Suche nach Uniqueness-Verletzungen.

Der Worker-Vertrag#

MaxLinksPerImport=50_000, ImportRunBudget=30*time.Minute, progressEvery=50, errorLogCap=1_000. Über alle fünf Migrationsanbieter hinweg geteilt. Diese Konstanten sind der Vertrag, von dem das Dashboard-Polling-UI ausgeht.

Ein TinyURL Pro-Konto mit 2.000 Aliasen trifft die API 20 Mal und ist in 3–5 Minuten fertig. Ein Bulk-Konto mit 20.000 Aliasen benötigt 200 Roundtrips und ist in 15–20 Minuten fertig. Über 50.000 Aliase schlägt der Worker hart fehl mit der Anweisung, eine E-Mail an [email protected] für eine gechunkte Migration zu senden; der chunked migration-Pfad ist in v1 nur als Concierge-Service verfügbar.

Resumability und das Deploy-Problem#

Dasselbe Abwägung wie bei den ersten drei Migrationen. Der Worker ist "in-process"; ein Deploy während des Imports beendet die Goroutine. Der "Stuck-Sweep"-Cron schaltet jede running-Zeile ohne Fortschritt in 30 Minuten auf failed. Ein erneuter Durchlauf ist dank Suffix und Skip idempotent.

Für Konten mit mehr als 10.000 Aliasen würde sich Resumability lohnen – wir würden den TinyURL page-Cursor in import_jobs.source_filter aufzeichnen und ab der letzten abgeschlossenen Seite fortfahren. Die vier anderen Migrationsanbieter werden von derselben Änderung profitieren, sobald wir sie bereitstellen; das Design ist geteilt.

CSV-Fallback#

Für Benutzer mit Bulk-Plänen, die einen exportierten CSV-Datensatz haben, aber kein aktives API-Token mehr besitzen, führen wir einmalige CSV-Jobs über den Posteingang aus – E-Mail an [email protected]. Wir haben kein Self-Service-CSV-Upload-Formular bereitgestellt, da der REST-Pfad den Standardfall abdeckt und der CSV-Pfad eine pro Konto angepasste Schema-Aufbereitung erfordert, die von Hand besser erledigt wird als von einem fehleranfälligen generischen Parser.

Was kommt als Nächstes#

Ein Anbieter muss noch landen:

  • Dub.coGET /api/links?projectSlug=…&limit=100. Ordner werden in Tags umgewandelt. Die sauberste API der fünf.

Nach Dub ist der Tier-3-Rollout abgeschlossen. Fünf Migrations-Landings, fünf Engineering-Blogbeiträge, ein geteiltes Worker-Grundgerüst, ein geteiltes Dashboard-Polling-UI.

Wenn Sie bisher gewartet haben, weil die TinyURL-Migration nicht dokumentiert war: Sie ist jetzt dokumentiert. Probieren Sie es aus – vom Pro/Bulk-Token bis zum letzten importierten Link in unter sieben Minuten bei typischen Konten.

Verwandtes auf dem Blog#

Elido testen

URL-Shortener mit EU-Hosting: eigene Domains, tiefe Analytik und eine offene API. Kostenloser Tarif — keine Kreditkarte nötig.

Tags
tinyurl migration
url shortener
go worker
data migration
engineering
tier 3 integrations

Weiterlesen