Der Tech-Stack von SEOJuice

Vadim Kravcenko
Vadim Kravcenko
· Updated · 5 min read

Als ich angefangen habe, SEOJuice zu bauen, war die erste echte Entscheidung weder ein Feature noch ein Preismodell. Es war eine Frage, zu der ich immer wieder zurückkam: Greife ich zu dem Stack, den ich bereits in- und auswendig kenne, oder zu dem, der in einem „How We Built It“-Blogpost beeindruckender aussieht? Ich habe mich für die langweilige Variante entschieden. Und ich würde es wieder tun, denn langweilige Technologie, die du wirklich tief verstehst, schlägt trendige Technologie, die du nebenbei erst noch lernst, jedes einzelne Mal. (Frag mich nach den drei Wochen, die ich damit verbrannt habe, eine Graph-Datenbank zu prüfen, bevor ich akzeptiert habe, dass PostgreSQL alles kann, was ich brauche.)

In diesem Artikel zeige ich dir den Tech-Stack von SEOJuice: ein transparenter Blick auf jede Schicht der Infrastruktur – nicht nur auf die finalen Entscheidungen, sondern auch auf die Abwägungen dahinter. Wenn du als Gründer gerade deinen eigenen Stack bewertest, hoffe ich, dass dir die Begründungen mehr helfen als die Labels.

Tech-Stack-Philosophie

Meine Philosophie lässt sich auf drei Regeln herunterbrechen, die ich auf die harte Tour gelernt habe, nachdem ich jahrelang Side Projects betrieben hatte, lange bevor es SEOJuice gab:

A high-quality stock photo showing a technical professional analyzing data or AI-driven processing on a laptop or workstation, visually matching the section about processing pipelines and AI systems.
A high-quality stock photo showing a technical professional analyzing data or AI-driven processing on a laptop or workstation, visually matching the section about processing pipelines and AI systems.. Source: Semrush Blog
A realistic photo of a developer building or maintaining backend infrastructure, with code on screens and a professional workspace that supports the article's discussion of pragmatic stack decisions, Django, ASGI, and Nginx.
A realistic photo of a developer building or maintaining backend infrastructure, with code on screens and a professional workspace that supports the article's discussion of pragmatic stack decisions, Django, ASGI, and Nginx.. Source: Semrush Blog

Regel 1: Kontrolliere den kritischen Pfad selbst. Wenn die Kernfunktion deines Produkts von einer externen API abhängt, gibst du jemand anderem den Ausschalter in die Hand. Die Crawling-Engine von SEOJuice, die Link-Analyse und die Scoring-Algorithmen laufen alle auf Infrastruktur, die ich kontrolliere. In dem Moment, in dem du dein zentrales Differenzierungsmerkmal auslagerst, bist du kein Produkt mehr, sondern wirst zum Reseller.

Regel 2: Wähle Technologien, die du um 2 Uhr morgens debuggen kannst. Ich habe FastAPI für das Backend in Betracht gezogen. In Benchmarks ist es schneller und moderner, und die asynchrone Architektur ist sauberer gelöst. Aber ich arbeite seit 2016 mit Django. Wenn Sentry um Mitternacht losgeht, will ich nicht erst 40 Minuten Dokumentation lesen – ich will sofort wissen, welche Middleware gerade Ärger macht. Vertrautheit ist keine Faulheit, sondern operative Reife.

Regel 3: Minimiere bewegliche Teile. Jeder zusätzliche Service in deiner Architektur ist noch etwas, das ausfallen kann, noch etwas, das Monitoring braucht, noch eine Abhängigkeit, die du aktualisieren musst. Ich zähle die Services in meiner docker-compose-Datei so, wie ein Backpacker jedes Gramm zählt.

Back-End-Stack

Im Herzen von SEOJuice steckt Django. Ich habe es Flask vorgezogen (zu minimalistisch für ein Produkt dieser Komplexität), FastAPI (großartig für APIs, aber ich brauchte Djangos Admin, ORM und Template-Engine) und Rails (ich kenne Ruby nicht gut genug, um es blind zu debuggen). Djangos „batteries included“-Philosophie bedeutete, dass ich nicht die ersten drei Monate damit verbracht habe, ein Authentifizierungssystem, ein Admin-Panel und ein Migrations-Framework aus einzelnen Paketen zusammenzustecken. Der Nachteil ist, dass Django sich für einfache Microservices schwergewichtig anfühlen kann – aber SEOJuice ist kein einfacher Microservice. Es ist ein Monolith mit 15+ Apps, und genau damit kommt Django gut klar.

Die Anwendung läuft auf ASGI via Uvicorn, hinter Nginx als Reverse Proxy. Ich bin ungefähr ein Jahr nach dem Start von Gunicorn (WSGI) auf Uvicorn gewechselt, als ich WebSocket-Support für Echtzeit-Benachrichtigungen und den MCP-Server hinzugefügt habe. Diese Migration war überraschend schmerzfrei – einer der Vorteile von Djangos schrittweiser ASGI-Einführung. Cloudflare sitzt vor der gesamten Infrastruktur und übernimmt DNS, SSL-Terminierung und DDoS-Schutz. Ich habe erlebt, wie Cloudflare Traffic-Spitzen abgefangen hat, die meine Server sonst mühelos in die Knie gezwungen hätten.

Alle Server laufen auf Linux, gehostet bei Hetzner. Warum Hetzner statt AWS? Ganz ehrlich: Kosten. Ein dedizierter Hetzner-Server mit 64GB RAM kostet ungefähr so viel, wie eine vergleichbare EC2-Instanz für eine Woche kostet. Für ein eigenfinanziertes Produkt ist dieser Unterschied enorm wichtig. Der Nachteil ist weniger Automatisierung – kein Auto-Scaling, kein gemanagtes Kubernetes. Ich mache Deployments mit Docker und ein paar Shell-Skripten. Das ist nicht glamourös, aber es funktioniert, und das Geld, das ich spare, fließt direkt in die Produktentwicklung.

Die Datenbank ist PostgreSQL mit der pgvector-Erweiterung. Ich habe MongoDB früh getestet (2022 hat es gefühlt jeder benutzt) und schnell gemerkt, dass SEO-Daten stark relational sind – Seiten gehören zu Websites, Keywords gehören zu Seiten, Links verbinden Seiten miteinander. Eine dokumentenorientierte Datenbank hätte bedeutet, die Hälfte von dem nachzubauen, was Postgres dir kostenlos mitliefert. Der ausschlaggebende Punkt war dann die pgvector-Erweiterung: Damit kann ich Embedding-Vektoren direkt neben den relationalen Daten speichern und abfragen. Das treibt unser Matching für Content-Ähnlichkeit und unsere KI-Funktionen an, ohne dass ich eine separate Vektordatenbank brauche.

Für Hintergrundjobs nutze ich Celery mit Redis als Broker. Celery bekommt in der Python-Community viel Kritik ab, und ein Teil davon ist absolut berechtigt – die Dokumentation ist verstreut, die Konfigurationsoptionen sind erschlagend, und das Debugging von Task-Fehlern kann einen in den Wahnsinn treiben. Aber ich habe bisher nichts Besseres gefunden für das schiere Volumen an Hintergrundarbeit, das SEOJuice erledigt: Tausende Seiten crawlen, NLP-Analysen durchführen, Reports generieren, Backlinks überwachen. Ich habe mir Dramatiq und Huey als schlankere Alternativen angesehen. Dramatiq ist wirklich gut, aber Celerys Ökosystem (beat scheduler, flower monitoring, django-celery-results) hat am Ende gewonnen.

Die Authentifizierung läuft über Auth0. Für ein früheres Projekt habe ich mal ein eigenes Authentifizierungssystem gebaut und peinlich viel Zeit mit Edge Cases bei Passwort-Resets, Rate Limiting und MFA-Flows verbracht. Auth0 kümmert sich um all das. Die Kosten skalieren mit den Nutzern, was an bestimmten Schwellenwerten wehtut, aber die eingesparte Engineering-Zeit ist ein Vielfaches des Abopreises wert.

Alles ist mit Docker containerisiert. Meine Entwicklungsumgebung und die Produktionsumgebung laufen in identischen Containern. Das hat eine ganze Klasse von „works on my machine“-Bugs eliminiert, die meine früheren Projekte geplagt haben. Sentry überwacht Exceptions in Echtzeit – ich kann einen von Nutzern gemeldeten Bug in unter einer Minute von ihrer Sitzung bis zur exakten Codezeile zurückverfolgen.

Front-End-Stack

Ich habe ganz bewusst entschieden, React, Vue und jedes andere JavaScript-Framework zu vermeiden. Das SEOJuice-Dashboard ist serverseitig gerendertes HTML mit Tailwind CSS und Alpine.js für Interaktivität. Das ist die Entscheidung, für die ich von anderen Entwicklern am meisten Gegenwind bekomme, und ich verstehe auch warum – es fühlt sich ein bisschen so an, als würde man mit Handwerkzeug bauen, obwohl es Elektrowerkzeuge gibt.

Hier ist meine Begründung: SEOJuice ist ein datenlastiges Dashboard. Nutzer schauen sich Tabellen, Charts und Reports an. Sie brauchen kein kollaboratives Echtzeit-Editing und kein komplexes clientseitiges Zustandsmanagement. Serverseitiges Rendering bedeutet, dass jede Seite schnell lädt, die anfängliche Datenmenge klein bleibt und ich keine separate Frontend-Build-Pipeline, keine zusätzliche öffentliche API-Schicht und keine Library für Zustandsverwaltung pflegen muss. Alpine.js übernimmt Dropdowns, Modals und interaktive Filter. Für die wenigen Stellen, an denen ich mehr Interaktivität brauche (das Echtzeit-Monitoring-Dashboard), nutze ich htmx, um HTML-Fragmente ohne vollständigen Reload auszutauschen.

Statische Assets laufen über das CDN von Bunny.net. Ich habe auch das CDN von Cloudflare getestet (das ich ohnehin für DNS nutze), fand aber Bunnys Preisgestaltung pro Request für meine Traffic-Muster besser kalkulierbar. Der Unterschied ist marginal – beides würde funktionieren.

Verarbeitung und AI

Ein erheblicher Teil dessen, was SEOJuice nützlich macht, besteht darin, große Datenmengen zu verarbeiten und AI für Funktionen einzusetzen, die man manuell kaum sinnvoll bauen könnte.

Für Sprachmodelle integriere ich OpenAI und Claude. Ich nutze unterschiedliche Modelle für unterschiedliche Aufgaben, basierend auf monatelangen Tests: GPT-4o für strukturierte Datenextraktion (es hält sich zuverlässiger an JSON-Schemas), Claude für Content-Analyse und Empfehlungen (es schreibt natürlicher und geht besser mit Nuancen um). Ich habe auch versucht, Open-Source-Modelle lokal zu betreiben – erst Llama 2, dann Llama 3 – aber die Qualitätslücke für den produktiven Einsatz war noch zu groß, um die Infrastrukturkosten zu rechtfertigen. Diese Rechnung verändert sich alle paar Monate, deshalb prüfe ich das regelmäßig neu.

Ich nutze pgvector für Embedding Search statt einer dedizierten Vektordatenbank wie Pinecone oder Weaviate. Vektoren in PostgreSQL direkt neben den restlichen Daten zu haben bedeutet, dass ich Ergebnisse aus der Embedding-Ähnlichkeit in einem einzigen SQL-Statement mit relationalen Abfragen verknüpfen kann. Die Performance ist für unseren Maßstab absolut ausreichend. Wenn ich Milliarden Vektoren verarbeiten würde, bräuchte ich etwas Spezialisierteres. Bei Millionen kommt Postgres problemlos mit.

Auf der NLP-Seite übernehmen NumPy, NLTK und Scikit-learn die Schwerstarbeit für Keyword-Extraktion, Content-Scoring und Klassifikation. Diese Libraries sind nicht aufregend, aber sie sind battle-tested. Wenn ich eine TF-IDF-Analyse über 50,000 Seiten laufen lasse, brauche ich ein korrektes Ergebnis, kein innovatives.

Für das Crawlen von JavaScript-lastigen Websites nutze ich Playwright, das in einem separaten Container läuft. Das ist ressourcenintensiver als einfache HTTP-Requests, aber moderne Websites rendern kritische Inhalte oft über JavaScript. Wenn unser Crawler sie nicht sehen kann, können wir sie auch nicht analysieren. Playwright kommt mit SPAs, lazy geladenem Content und clientseitigem Routing klar, das für einen klassischen Crawler unsichtbar wäre.

Zusätzliche Tools und Services

Bei der unterstützenden Infrastruktur war ich am ehesten bereit, externe Services zu nutzen, weil keiner dieser Bausteine mein eigentliches Differenzierungsmerkmal ist:

Crisp für Live-Chat. Ich habe zuerst Intercom ausprobiert – zu teuer und zu komplex für ein One-Person-Support-Team. Crisp macht das, was ich brauche, zu einem Bruchteil der Kosten.

Customer.io für E-Mails. Transaktionale E-Mails (Passwort-Resets, Report-Zustellung), Onboarding-Sequenzen und Produkt-Updates laufen alle über Customer.io. Ich bin von einem einfacheren Setup gewechselt (Djangos eingebautes E-Mail-System mit SendGrid), weil ich verhaltensbasierte Trigger brauchte – „schicke eine Tipp-Mail, wenn der Nutzer seine WordPress-Seite nicht innerhalb von 3 Tagen verbunden hat.“

Paddle für Zahlungen. Ich habe mit Stripe angefangen und bin dann zu Paddle als Merchant of Record migriert. Der Grund war komplett pragmatisch: Paddle übernimmt die Berechnung, Einziehung und Abführung der VAT für jedes Land. Als eigenfinanzierter europäischer Gründer, der global verkauft, wäre der Aufbau eines eigenen Systems für Tax Compliance ein Vollzeitjob gewesen. Paddle nimmt einen größeren Anteil als Stripe, aber dafür verschwindet eine komplette Kategorie operativer Last.

ChartMogul für Umsatzanalysen. MRR, Churn Rate, LTV, Expansion Revenue – ich brauche diese Zahlen korrekt und automatisch aktualisiert. Ich könnte sie auch aus Paddles API selbst berechnen, aber ChartMogul macht das besser und zeigt Trends, auf die ich selbst vielleicht gar nicht schauen würde.

Für Besucheranalysen betreibe ich eine selbstgehostete Instanz von Plausible. Keine Cookies, keine Consent-Banner, kein Versenden von Besucherdaten an Google. Es zeigt mir Traffic-Quellen, Top-Seiten und Referrer – und das ist ehrlich gesagt wirklich alles, was ich brauche. (Ich habe in unserem Guide zu Open-Source-SEO-Tools ausführlicher über Plausible geschrieben.)

Was ich ändern würde

Kein Stack ist perfekt, und ich habe inzwischen genug gelernt, um zu wissen, was ich anders machen würde, wenn ich heute noch einmal bei null anfangen müsste:

Ich würde früher in Kubernetes investieren. Nicht an Tag eins – das wäre für ein MVP Overkill – aber ungefähr zu dem Zeitpunkt, an dem ich 10 Hintergrund-Worker erreicht habe. Container mit Shell-Skripten und systemd zu orchestrieren funktioniert, bis es plötzlich nicht mehr funktioniert, und der Übergang zu echter Orchestrierung unter laufender Produktionslast ist nichts für schwache Nerven.

Ich würde die API früher vom Monolithen trennen. Dass Dashboard, öffentliche API, WordPress-Plugin-API und der MCP-Server alle denselben Django-Prozess teilen, bedeutet, dass ein Spike im API-Traffic das Dashboard verlangsamen kann. Ich extrahiere diese Teile nach und nach in separate Services, aber sauberer wäre es gewesen, das von Anfang an so zu entwerfen.

Ich würde die Kernentscheidungen nicht ändern – Django, PostgreSQL, Celery, serverseitig gerendertes HTML. Diese Entscheidungen haben sich über zwei Jahre im Produktivbetrieb bewährt, und die Einfachheit, die sie liefern, ist mehr wert als die möglichen Performance-Gewinne, die ich mit trendigeren Alternativen vielleicht bekommen hätte.

Fazit

Als Solo-Gründer ist die gefährlichste Falle, den eigenen Stack für das Hacker-News-Publikum zu bauen statt für die tatsächlichen Anforderungen des Produkts. Jede Technologieentscheidung, die ich hier beschrieben habe, wurde von einem konkreten Bedarf getrieben, gegen Alternativen abgewogen und deshalb getroffen, weil sie mir erlaubt hat, schneller und mit weniger Überraschungen auszuliefern. Das Ergebnis ist ein System, das ich alleine betreiben, schnell debuggen und ohne komplettes Umschreiben erweitern kann.

Aber das ist erst der Anfang. Der Stack entwickelt sich weiter, genau wie das Produkt – ich arbeite kontinuierlich daran, SEOJuice zu verbessern, und die Infrastruktur muss dieses Tempo mitgehen. Wenn du als Gründer gerade vor denselben Entscheidungen stehst, hoffe ich, dass dir mein Denkprozess einiges an Versuch und Irrtum erspart, durch das ich mich gearbeitet habe.

Lass uns weiterbauen.

Viele Grüße,
Vadim

Weiterführende Artikel:

SEOJuice
Stay visible everywhere
Get discovered across Google and AI platforms with research-based optimizations.
Works with any CMS
Automated Internal Links
On-Page SEO Optimizations
Get Started Free

no credit card required