SSD Nodes Learn 🎉 VPS ab $4.99/Monat
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-07

Langfuse selbst hosten: Ressourcen, TLS und Backups

Langfuse auf dem eigenen VPS betreiben: Mindestressourcen, gepinnte Image-Tags, TLS, ClickHouse-Retention gegen volle Platten und getestete Backups.

Warum einen AI-Agent überhaupt nachverfolgen?

Sie hosten Langfuse selbst, um zu sehen, was Ihr Agent bei einem Lauf tatsächlich ausgeführt hat. Langfuse ist ein Open-Source-Observability-Tool für LLMs (Large Language Models). Es erfasst jeden Prompt, jede Modellantwort, jeden Tool-Aufruf und jedes Token. Anschließend gruppiert es diese Daten unter einem Trace, den Sie öffnen und auswerten können. Wenn Sie Langfuse auf Ihrem eigenen VPS betreiben, verlassen diese Prompts niemals einen Server, den Sie kontrollieren.

Der Grund dafür ist einfach. Sie können ein Kosten- oder Qualitätsproblem nicht beheben, wenn Sie es nicht sehen. Eine Anbieterrechnung zeigt Ihnen, dass der Dienstag viermal so viel gekostet hat wie der Montag. Ein Trace zeigt, welcher Agent-Lauf dafür verantwortlich war, welcher Prompt auf 40,000 Token angewachsen ist und welche Retry-Schleife neunmal lief, bevor sie abbrach. Die Rechnung liefert die Zahl. Der Trace zeigt den Code, der sie verursacht hat.

In diesem Leitfaden werden drei Begriffe verwendet. Ein Trace ist ein vollständiger Lauf Ihres Agenten von Anfang bis Ende. Eine Observation ist ein einzelner Schritt innerhalb dieses Laufs: ein Span für gewöhnlichen Code und eine Generation für einen Aufruf an ein Modell. Ein Score ist eine Zahl, die einem Trace zugeordnet ist und aus einer menschlichen Bewertung oder einem automatisierten Evaluator stammt. Langfuse verwendet OpenTelemetry (OTel), den herstellerneutralen Standard für verteiltes Tracing. Daher kann Ihre bereits vorhandene Instrumentierung auf Langfuse zeigen.

Was Self-Hosting von Langfuse tatsächlich ausführt

Langfuse v4 besteht nicht aus einem Container. Es besteht aus zwei Anwendungscontainern und vier Speicherdiensten. Auf einem einzelnen VPS laufen alle sechs auf Ihrem System.

  • langfuse-web stellt die Weboberfläche und die Ingestion-API bereit.
  • langfuse-worker leert die Warteschlange im Hintergrund. Der Container verarbeitet Ingestion-Batches, berechnet Kosten und führt den nächtlichen Aufbewahrungsjob aus.
  • Postgres speichert Transaktionsdaten wie Benutzer, Organisationen, Projekte, API-Schlüssel und Prompts.
  • ClickHouse speichert die eigentlichen Trace-Daten, also Observations und Scores. Es ist ein für analytische Abfragen entwickelter Column Store. Deshalb antwortet ein Dashboard über mehr als hundert Millionen Zeilen weiterhin schnell.
  • Redis ist die Warteschlange und der Cache zwischen Webanwendung und Worker.
  • MinIO stellt S3-kompatiblen Objektspeicher auf dem System bereit. Es speichert jedes eingehende Rohereignis sowie alle angehängten Medien.

Langfuse veröffentlicht Mindestressourcen für die drei Komponenten, die die eigentliche Verarbeitung übernehmen.

ChartLangfuse published minimum resources per component
The data behind this chart
[
  {
    "label": "ClickHouse",
    "cpu_cores": 2,
    "memory_gib": 8
  },
  {
    "label": "Langfuse web",
    "cpu_cores": 2,
    "memory_gib": 4
  },
  {
    "label": "Langfuse worker",
    "cpu_cores": 2,
    "memory_gib": 4
  }
]

ClickHouse allein benötigt 8 GiB Arbeitsspeicher. Der Webcontainer und der Worker benötigen jeweils 4 GiB. Das sind die veröffentlichten Mindestwerte für die 3 von Langfuse dimensionierten Komponenten. Postgres, Redis und MinIO benötigen zusätzlich Arbeitsspeicher. Die Docker-Compose-Anleitung des Projekts empfiehlt einen Rechner mit 4 Kernen, 16 GiB Arbeitsspeicher und etwa 100 GiB Speicherplatz. Das entspricht dieser Berechnung und enthält keinen zusätzlichen Aufschlag.

Versuchen Sie das nicht mit einem Tarif mit 2 GiB. ClickHouse startet und akzeptiert zunächst einige Zeit Schreibvorgänge. Danach beendet sich der Dienst während eines Hintergrund-Merges, weil ein Merge große Tabellenteile in den Arbeitsspeicher lädt. docker compose ps meldet dann den clickhouse-Container als restarting. dmesg enthält eine Zeile wie Out of memory: Killed process 1234 (clickhouse-serv). Außerdem liefern alle Langfuse-Dashboards den Status 500 zurück. Bei geringerer Speicherauslastung verweigert ClickHouse stattdessen die Abfrage und protokolliert DB::Exception: Memory limit (total) exceeded. Acht GiB sind für einen einzelnen Entwickler mit einigen tausend Traces pro Tag ausreichend. Planen Sie mit 16 GiB.

Langfuse mit Docker Compose bereitstellen

Klonen Sie das Repository. Der Stack, die Konfiguration und die Standardumgebung befinden sich in docker-compose.yml.

git clone https://github.com/langfuse/langfuse.git
cd langfuse

Jeder Wert, den Sie ändern müssen, ist in dieser Datei mit # CHANGEME markiert. Erzeugen Sie zuerst die drei Anwendungsgeheimnisse.

openssl rand -base64 32   # NEXTAUTH_SECRET
openssl rand -base64 32   # SALT
openssl rand -hex 32      # ENCRYPTION_KEY

ENCRYPTION_KEY muss 256 Bit umfassen und als 64 hexadezimale Zeichen geschrieben sein. Genau das gibt openssl rand -hex 32 aus. Damit werden vertrauliche Werte im Ruhezustand verschlüsselt, darunter alle LLM-Provider-Schlüssel, die Sie in der Instanz speichern. Wenn Sie den Wert ändern, nachdem bereits Daten vorhanden sind, können diese Datensätze nicht mehr entschlüsselt werden. Behandeln Sie den Wert daher ab dem ersten Start als dauerhaft. SALT wird zum Hashen Ihrer Langfuse-API-Schlüssel verwendet. Eine Änderung macht alle Schlüssel ungültig, die Ihre Agents bereits verwenden.

Setzen Sie anschließend POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH und MINIO_ROOT_PASSWORD. Das MinIO-Passwort erscheint an vier Stellen: einmal als MINIO_ROOT_PASSWORD und danach nochmals als LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY und LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. Wenn eine Stelle fehlt, weist MinIO diesen Client mit SignatureDoesNotMatch zurück. Die Meldung erscheint im Worker-Log, während die Weboberfläche weiterhin fehlerfrei aussieht. Diese Werte in einer Env-Datei statt in der versionierten Compose-Datei zu speichern, ist das in Docker-Compose-Env-Dateien und Secrets beschriebene Vorgehen.

Image-Tags vor dem Start festlegen

Die mitgelieferte Datei verwendet langfuse/langfuse:4 und langfuse/langfuse-worker:4. Diese Tags ändern sich. Langfuse führt seine Postgres- und ClickHouse-Migrationen beim Start automatisch aus. Ein routinemäßiges docker compose pull Monate später wird dadurch zu einer ungeplanten Schema-Migration auf einer Datenbank, die Sie an diesem Morgen nicht gesichert haben. Fixieren Sie beide auf eine Version in einer docker-compose.override.yml. Compose führt diese Datei mit Vorrang vor der mitgelieferten Datei zusammen, sodass ein späteres git pull Ihre Änderungen nicht überschreibt.

services:
  langfuse-web:
    image: docker.io/langfuse/langfuse:4.3.1
  langfuse-worker:
    image: docker.io/langfuse/langfuse-worker:4.3.1

Version 4.3.1 war im August 2026 die aktuelle Version der 4.3-Reihe (4.4.0 wurde inzwischen veröffentlicht). Prüfen Sie die GitHub-Releases-Seite des Projekts, fixieren Sie die am Tag der Bereitstellung aktuelle Version und ändern Sie diese Versionsnummer später bewusst. Die Storage-Images in der mitgelieferten Datei sind bereits auf Major-Versionen fixiert: postgres:17, clickhouse-server:25.12 und redis:7. Für diese Images sollten Sie genauso vorgehen.

Starten Sie den Stack.

docker compose up -d
docker compose ps
docker compose logs -f langfuse-worker

Beim ersten Start werden die Migrationen ausgeführt. Warten Sie daher ein bis zwei Minuten, bevor Sie eine Antwort erwarten. docker compose ps sollte sechs Services im Status running auflisten. Wenn der Worker in einer Neustartschleife läuft, enthält sein Log den Grund: CLICKHOUSE_MIGRATION_URL verwendet das ClickHouse-Native-Protokoll auf Port 9000, nicht den HTTP-Port 8123. Eine Konfiguration mit Port 8123 schlägt daher fehl, während der Webcontainer weiterhin fehlerfrei aussieht.

Prüfen Sie den Zustand direkt auf dem Server.

curl -s "http://localhost:3000/api/public/health?failIfDatabaseUnavailable=true"
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/public/ready

Ein einfacher /api/public/health-Aufruf bestätigt nur, dass der API-Prozess läuft. Die Datenbank wird dabei absichtlich nicht geprüft, damit der Service bei kurzen Ausfällen von Postgres weiterhin Anfragen verarbeitet. Die Variante failIfDatabaseUnavailable=true eignet sich für die Überwachung. Sie gibt 503 zurück, wenn die Datenbank nicht erreichbar ist. /api/public/ready gibt 200 zurück, sobald die Migrationen abgeschlossen sind und der Container Netzwerkverkehr annimmt. Beide Prüfungen verwenden gewöhnliches HTTP. Daher kann eine Uptime-Kuma-Statusseite sie überwachen und Ihnen melden, dass der Stack ausgefallen ist, bevor Ihre Agents dies feststellen.

TLS vorschalten und die zusätzlichen Ports schließen

Die mitgelieferte Compose-Datei veröffentlicht 3000:3000 für den Webcontainer und 9090:9000 für MinIO. Beide Dienste binden an alle Schnittstellen. Bei einer öffentlichen IP-Adresse erreicht jeder, der Port 3000 scannt, Ihre Registrierungsseite. Wer Port 9090 scannt, greift auf den Bucket mit Ihren Roh-Prompts zu.

Eine Firewall-Regel allein schließt diese Ports nicht. Docker schreibt eigene DNAT-Regeln in die Tabelle nat. Diese Regeln werden ausgewertet, bevor die Filterregeln von ufw das Paket sehen. Daher lässt ufw deny 3000 den veröffentlichten Port weiterhin offen. Dieses Problem tritt so häufig auf, dass es dafür einen eigenen Leitfaden gibt: warum veröffentlichte Docker-Ports ufw umgehen. Binden Sie die Ports stattdessen in Ihrer Override-Datei an die Loopback-Schnittstelle.

services:
  langfuse-web:
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      NEXTAUTH_URL: https://langfuse.example.com
  minio:
    ports:
      - "127.0.0.1:9090:9000"
      - "127.0.0.1:9091:9001"

NEXTAUTH_URL muss die exakte öffentliche Adresse einschließlich des Schemas enthalten, weil der Login-Ablauf daraus die Callback-URL erstellt. Lassen Sie den Wert hinter einem HTTPS-Proxy auf http://localhost:3000 stehen, führt der Anmelde-Roundtrip den Browser zu einer Adresse, die er nicht erreichen kann.

Leiten Sie nun einen Reverse Proxy auf 127.0.0.1:3000 und lassen Sie ihn das Zertifikat verwalten. Traefik im selben Compose-Projekt ist die übliche Wahl. Die Routing-Labels werden in mehrere Anwendungen hinter einem Traefik-Reverse-Proxy betreiben beschrieben. Caddy erledigt dieselbe Aufgabe mit zwei Zeilen, wenn Langfuse die einzige Anwendung auf dem Server ist. Prüfen Sie mit curl -sI https://langfuse.example.com/api/public/ready. Bestätigen Sie anschließend von einem zweiten Rechner aus, dass curl http://YOUR_IP:3000 nun mit einem Timeout fehlschlägt.

Ein Hinweis zu MinIO: Langfuse stellt angehängte Medien über presigned URLs bereit, die auf diesen S3-Endpunkt verweisen. Wenn Sie multimodale Traces mit Bildern oder Audio verwenden, werden diese Anhänge bei einem ausschließlich an Loopback gebundenen MinIO nicht geladen. Lesen Sie vor dem Proxying die Konfigurationsseite zum Blob-Speicher. Der in die presigned URL geschriebene Endpunkt muss mit dem veröffentlichten Endpunkt übereinstimmen. Reine Text-Traces sind davon nicht betroffen.

Erstellen Sie Ihr Konto beim ersten Aufruf und behalten Sie anschließend die Kontrolle über die Instanz. Setzen Sie LANGFUSE_ALLOWED_ORGANIZATION_CREATORS auf Ihre eigene E-Mail-Adresse. So kann ein Fremder, der die Seite erreicht, keine Organisation auf Ihrem Server erstellen.

Senden Sie Ihren ersten Trace

Erstellen Sie in der Weboberfläche ein Projekt und kopieren Sie dessen öffentlichen und geheimen Schlüssel aus den Projekteinstellungen. Das Python-SDK liest drei Umgebungsvariablen ein.

export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://langfuse.example.com"

LANGFUSE_BASE_URL ist in SDK v4, das im März 2026 veröffentlicht wurde, der Variablenname. Älterer Code und ältere Anleitungen verwenden LANGFUSE_HOST. Wenn Ihre Traces statt auf Ihrem Server bei Langfuse Cloud ankommen, liegt das daran, dass die Basis-URL nicht gesetzt ist. Der Standardwert verweist auf die gehostete Instanz.

pip install langfuse opentelemetry-instrumentation-anthropic anthropic
import os
from anthropic import Anthropic
from langfuse import get_client, observe
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor

AnthropicInstrumentor().instrument()
langfuse = get_client()
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

@observe(as_type="tool")
def lookup_order(order_id: str) -> str:
    return f"order {order_id}: shipped"

@observe()
def handle_request(question: str) -> str:
    context = lookup_order("A-1042")
    message = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=512,
        messages=[{"role": "user", "content": f"{context}\n\n{question}"}],
    )
    return message.content[0].text

if __name__ == "__main__":
    assert langfuse.auth_check()
    print(handle_request("Where is my order?"))
    langfuse.flush()

Der Dekorator @observe öffnet eine Observation um die Funktion, erfasst deren Argumente und Rückgabewert und verschachtelt sie unter der aktuell aktiven Observation. AnthropicInstrumentor ist die OpenTelemetry-Instrumentierung für den Anthropic-Client. Sie wandelt jeden Aufruf von messages.create in eine Generation um, die den Modellnamen, den Token-Verbrauch und die Latenz enthält. An der Aufrufstelle sind keine Änderungen erforderlich.

Zwei Aufrufe übernehmen die Prüfung für Sie. langfuse.auth_check() gibt bei ungültigen Schlüsseln oder einer falschen Basis-URL False zurück. Das ist schneller, als nach der Ursache für ein leeres Dashboard zu suchen. langfuse.flush() wartet, bis die Warteschlange mit Spans gesendet wurde. Kurzlebige Prozesse benötigen diesen Aufruf, weil das SDK die Daten im Hintergrund bündelt und ein Skript, das sofort beendet wird, sein ungesendetes Datenpaket mitnimmt.

Warum wächst ClickHouse ständig?

Traces sind bei den meisten Self-Hosting-Installationen die am schnellsten wachsenden Daten. Jeder Agent-Lauf schreibt pro Schritt eine Zeile. Eingaben und Ausgaben werden vollständig gespeichert. Ein gesprächiger Agent mit langen Prompts erzeugt daher pro Tag deutlich mehr Daten als die Anwendung, die er überwacht. Wenn nichts unternommen wird, läuft die Festplatte mit ClickHouse voll. Eine volle Festplatte stoppt die Aufnahme neuer Daten, statt sie nur zu verlangsamen.

Hier wachsen zwei voneinander unabhängige Datenbestände. Sie benötigen daher zwei separate Maßnahmen.

Beim ersten Datenbestand handelt es sich um Ihre eigenen Trace-Daten. Die passende Maßnahme ist die Aufbewahrungseinstellung. Öffnen Sie die Projekteinstellungen in der Weboberfläche und legen Sie eine Aufbewahrungsdauer in Tagen fest. Langfuse akzeptiert mindestens 3 Tage. Ein nächtlicher Job sucht anschließend Traces, Beobachtungen, Bewertungen und Medienobjekte aus, die älter als dieses Zeitfenster sind, und löscht sie aus ClickHouse sowie aus dem Blob Storage. Der Job benötigt die Berechtigung DeleteObject für den Bucket. Die Root-Zugangsdaten von MinIO aus der standardmäßigen Compose-Datei verfügen bereits über diese Berechtigung. Die Löschung ist dauerhaft. Richten Sie daher zuerst einen Export in den Blob Storage ein, wenn Sie eine langfristige Historie benötigen. Schreiben Sie keine eigenen TTL-Klauseln für die Tabellen von Langfuse. Der Aufbewahrungsjob hält ClickHouse und den Bucket synchron. Eine manuelle TTL-Löschung entfernt die Daten dagegen nur auf einer Seite.

Wählen Sie das Zeitfenster anhand Ihrer tatsächlichen Nutzung. Kosten- und Qualitätsprüfungen erfolgen bei Daten, die einige Tage alt sind, nicht bei Daten, die mehrere Monate alt sind. 30 Tage sind für ein kleines Team ein sinnvoller Anfang. 14 Tage reichen aus, wenn Sie einen Trace nur öffnen, sobald etwas fehlschlägt.

Beim zweiten Datenbestand handelt es sich um die systemeigenen Systemprotokolltabellen von ClickHouse. Das überrascht viele, weil die Festplatte auch nach der Konfiguration der Aufbewahrung weiter wächst. ClickHouse schreibt trace_log, text_log, opentelemetry_span_log, metric_log und asynchronous_metric_log für die eigene Diagnose. Diese Tabellen werden ohne TTL ausgeliefert. Langfuse liest sie nie. Ermitteln Sie zuerst, wohin der Speicher tatsächlich gegangen ist.

SELECT table, formatReadableSize(size) AS size, rows FROM (
    SELECT table, database, sum(bytes) AS size, sum(rows) AS rows
    FROM system.parts
    WHERE active
    GROUP BY table, database
    ORDER BY size DESC
)

Führen Sie den Befehl mit docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD" aus. Wenn sich Systemtabellen weit oben in der Liste befinden, deaktivieren Sie sie mit einem Konfigurations-Overlay. ClickHouse führt beim Start jede Datei in /etc/clickhouse-server/config.d/ mit seiner Hauptkonfiguration zusammen.

<clickhouse>
    <trace_log remove="1"/>
    <text_log remove="1"/>
    <opentelemetry_span_log remove="1"/>
    <asynchronous_metric_log remove="1"/>
    <metric_log remove="1"/>
</clickhouse>

Hängen Sie das Verzeichnis ein und starten Sie ClickHouse neu.

services:
  clickhouse:
    volumes:
      - ./clickhouse-config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:ro

Dadurch werden neue Schreibvorgänge beendet. Bereits auf der Festplatte vorhandene Zeilen bleiben jedoch bestehen. Geben Sie den Speicher daher mit DROP TABLE IF EXISTS system.trace_log und entsprechend für jede entfernte Tabelle ausdrücklich frei. Wenn Sie die Diagnosedaten behalten möchten, können Sie alternativ für jede Tabelle eine aggressive TTL konfigurieren, anstatt remove="1" zu verwenden. Die Langfuse-Dokumentation zur Skalierung beschreibt dieses Vorgehen ausführlich.

Eine weitere Tabelle sollten Sie kennen. blob_storage_file_log erfasst die in Ihren Bucket hochgeladenen Ereignisdateien. Wenn Sie für den Bucket zusätzlich eine Lifecycle-Richtlinie konfigurieren, legen Sie für die Tabelle eine passende TTL fest. Andernfalls können die beiden Aufbewahrungsmechanismen auseinanderlaufen.

ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL 30 DAY DELETE;

Richten Sie außerdem einen einfachen df -h-Alarm für die Datenfestplatte ein. Traces wachsen nicht gleichmäßig. Das Wachstum tritt an dem Tag auf, an dem Sie einen neuen Agenten ausrollen. Das erste Anzeichen dafür sollte nicht ein Fehler bei der Datenaufnahme sein.

Postgres und ClickHouse sichern

Ein Langfuse-Backup besteht aus drei Teilen. Postgres enthält Ihre Benutzer, Organisationen, Projekte und API-Schlüssel. ClickHouse enthält die Traces. MinIO enthält die Rohereignisse. Wenn Sie nur Postgres wiederherstellen, erhalten Sie eine funktionierende Anmeldung ohne Verlauf. Wenn Sie nur ClickHouse wiederherstellen, erhalten Sie einen Verlauf, den niemand ohne Anmeldung anzeigen kann.

Postgres ist ein einfaches pg_dump. Das empfehlen die Langfuse-Backup-Dokumente.

docker compose exec -T postgres pg_dump -U postgres postgres \
  | gzip > langfuse-pg-$(date +%F).sql.gz

Bei ClickHouse ist mehr Sorgfalt erforderlich, weil ein während laufender Merges kopiertes Datenverzeichnis kein konsistentes Backup ist. Auf einem einzelnen Host besteht der einfache Ansatz darin, den Container zu stoppen und das Volume zu archivieren.

docker compose stop clickhouse
docker volume ls | grep clickhouse
docker run --rm -v langfuse_langfuse_clickhouse_data:/data -v "$PWD":/backup alpine \
  tar czf /backup/langfuse-ch-$(date +%F).tar.gz -C /data .
docker compose start clickhouse

Verwenden Sie den von docker volume ls ausgegebenen Volume-Namen, nicht den im YAML eingetragenen Namen. Die Datei deklariert langfuse_clickhouse_data, und Compose versieht ihn mit dem Projektnamen. Ein Klon in einem Verzeichnis namens langfuse erzeugt daher langfuse_langfuse_clickhouse_data. Wenn dieser Name nicht stimmt, erstellt docker run ohne Fehlermeldung ein neues leeres Volume. Ihr Archiv enthält dann nichts.

Der Webcontainer schreibt jedes eingehende Ereignis in den Bucket, bevor der Worker es verarbeitet. Ein kurzer Stopp von ClickHouse bedeutet daher meist nur, dass der Worker die Verarbeitung anschließend wiederholt. Führen Sie das in einer ruhigen Stunde durch und halten Sie den Stopp kurz. Bei einer stärker ausgelasteten Instanz schreibt die eigene BACKUP DATABASE default TO S3(...)-Anweisung von ClickHouse ein konsistentes Backup, ohne den Server zu stoppen. MinIO ist der dritte Bestandteil. mc mirror oder die MinIO-Replikation in einen externen Bucket deckt diesen Teil ab. Unabhängig davon, welche Methode Sie verwenden, müssen Sie das Backup vom Server entfernen. Dafür sind verschlüsselte restic-Backups auf einem VPS vorgesehen.

Redis benötigt kein Backup. Redis enthält die Warteschlange und den Cache. Bei einem Verlust gehen daher nur die aktuell verarbeiteten Ereignisse verloren, nicht ältere Daten.

Der Hinweis zur Konsistenz ist berechtigt und sollte klar formuliert werden. Postgres und ClickHouse werden zu unterschiedlichen Zeitpunkten gesichert. Bei einer Wiederherstellung kann daher eine Projektzeile ohne Traces vorhanden sein oder Traces zu einem nicht mehr vorhandenen Projekt gehören. Langfuse toleriert diesen Zustand. Erstellen Sie beide Dumps trotzdem zeitnah nacheinander und in einem Zeitraum mit wenig Netzwerkverkehr. Der Ereignis-Bucket ist das eigentliche Sicherheitsnetz, weil Langfuse jedes eingehende Ereignis vor der Verarbeitung dort speichert.

Stellen Sie den Stack mindestens einmal in einer Testumgebung wieder her. So entdecken Sie einen falschen Volume-Namen jetzt und nicht erst während eines Ausfalls.

Worauf Sie zuerst achten sollten

Vier Dinge sind in der ersten Woche besonders wichtig.

  • Kosten pro Trace. Langfuse berechnet die Kosten anhand des Modellnamens und des Tokenverbrauchs. Sortieren Sie die Traces nach Kosten und lesen Sie den teuersten vollständig durch. Meist ist der Prompt zu groß geworden: Ein vollständiges Dokument wurde in den Kontext eingefügt oder eine Konversationshistorie wird nicht gekürzt. Sobald Sie das sehen, wird die Kontrolle über die Kosten eines KI-Agenten zu einer Engineering-Aufgabe statt zu einer Vermutung.
  • Aufteilung des Tokenverbrauchs nach Input und Output. Input-Tokens sind zahlreich und günstig, Output-Tokens sind weniger zahlreich und teuer, und gecachte Input-Tokens sind noch günstiger. Dieselbe Abrechnung wird in der Zählung des Tokenverbrauchs von Claude Code erläutert. Sie gilt auch für jeden Agenten, den Sie selbst schreiben.
  • Latenz-Perzentile. Der Median verbirgt das Problem. Bei p95 und p99 treten die Timeouts auf. Innerhalb einer Agentenschleife wird ein langsamer Tool-Aufruf bei p95 mit der Anzahl der Iterationen multipliziert.
  • Fehlgeschlagene Tool-Aufrufe. Filtern Sie die Beobachtungen nach der Ebene ERROR. Ein Tool, das in 5% der Fälle fehlschlägt, bleibt in einer aggregierten Erfolgsrate unsichtbar. In den Traces ist es deutlich zu sehen, wenn das Modell den Aufruf wiederholt und anschließend Tokens verbraucht, um den Fehler zu umgehen.

Legen Sie das Aufbewahrungsfenster fest und wählen Sie das Dashboard aus, das Sie wöchentlich am selben Tag prüfen. Tun Sie das am selben Tag, an dem Sie die Anwendung bereitstellen. Ein Observability-Tool, das niemand öffnet, ist eine Datenbank, die einen Datenträger füllt.

FAQ

Wie viel Arbeitsspeicher benötigt ein selbst gehostetes Langfuse?

Planen Sie 4 CPU-Kerne und 16 GiB Arbeitsspeicher ein. Das entspricht der Empfehlung des Langfuse-Docker-Compose-Leitfadens für eine einzelne virtuelle Maschine. Zusätzlich sollten Sie etwa 100 GiB Speicherplatz vorsehen. Die veröffentlichten Mindestanforderungen der Komponenten betragen 8 GiB für ClickHouse sowie jeweils 4 GiB für die Web- und Worker-Container. Postgres, Redis und MinIO benötigen darüber hinaus ebenfalls Arbeitsspeicher. Acht GiB reichen für die Instanz eines einzelnen Entwicklers aus. Zwei GiB reichen nicht aus: Der Kernel beendet ClickHouse während Hintergrundzusammenführungen, und dmesg zeigt Out of memory: Killed process.

Warum füllt sich mein ClickHouse-Datenträger weiter, nachdem ich eine Datenaufbewahrung festgelegt habe?

Die Einstellung zur Datenaufbewahrung gilt nur für die eigenen Daten von Langfuse. ClickHouse schreibt zusätzlich die Diagnosetabellen trace_log, text_log, opentelemetry_span_log, metric_log und asynchronous_metric_log. Diese werden ohne TTL ausgeliefert. Führen Sie system.parts mit einer Gruppierung nach Tabelle aus, um die größte Tabelle zu ermitteln. Deaktivieren Sie anschließend nicht benötigte Tabellen mit einem remove="1"-Eintrag in einer Datei unter /etc/clickhouse-server/config.d/. Starten Sie ClickHouse neu und löschen Sie die vorhandenen Tabellen, um den bereits belegten Speicherplatz freizugeben.

Wie lang ist die minimale Datenaufbewahrungsdauer in Langfuse?

Drei Tage. Die Aufbewahrung wird pro Projekt in den Projekteinstellungen oder über die Projects API festgelegt. Ein nächtlicher Job löscht Traces, Beobachtungen, Scores und Medienobjekte, die älter als dieser Zeitraum sind, aus ClickHouse und dem Blob-Speicher. Das Löschen kann nicht rückgängig gemacht werden. Konfigurieren Sie daher zuerst einen Export in einen Blob-Speicher, wenn Sie den Verlauf über diesen Zeitraum hinaus benötigen.

Muss ich sowohl Postgres als auch ClickHouse sichern?

Ja, da beide unterschiedliche Daten enthalten. Postgres speichert Benutzer, Organisationen, Projekte und API-Schlüssel. ClickHouse speichert die Trace-Daten selbst. Eine Wiederherstellung nur von Postgres ergibt eine Instanz, bei der Sie sich anmelden können, die jedoch keine Daten enthält. Sichern Sie außerdem den MinIO-Bucket, da er die Rohereignisse enthält, die Langfuse beim Eingang persistent speichert. Dieser kommt einer zentralen Datenquelle im Stack am nächsten.

Kann ich eine vorhandene OpenTelemetry-Konfiguration auf ein selbst gehostetes Langfuse ausrichten?

Ja. Langfuse v4 und seine v4-SDKs basieren auf OpenTelemetry. Die Anthropic- und OpenAI-OTel-Instrumentierungen exportieren direkt dorthin. Führen Sie in Python pip install langfuse opentelemetry-instrumentation-anthropic aus, rufen Sie AnthropicInstrumentor().instrument() einmal beim Start auf und setzen Sie LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY und LANGFUSE_BASE_URL auf Ihren eigenen Host. Prüfen Sie mit langfuse.auth_check(), ob die Verbindung funktioniert, bevor Sie nach einem fehlenden Dashboard suchen.