SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor

Self-host Langfuse per tracciare gli agenti AI

Esegui Langfuse sul tuo VPS: risorse minime reali, tag immagine bloccati, TLS, retention di ClickHouse prima che riempia il disco e backup verificati.

Perché tracciare un agente AI

Puoi eseguire Langfuse in self-hosting per vedere cosa ha effettivamente fatto il tuo agente durante un'esecuzione. Langfuse è uno strumento open source di osservabilità per LLM (large language model). Registra ogni prompt, ogni risposta del modello, ogni chiamata a uno strumento e ogni token, quindi li raggruppa in un'unica trace che puoi aprire e analizzare. Eseguirlo sul tuo VPS significa che questi prompt non lasciano mai un server sotto il tuo controllo.

Il motivo è semplice. Non puoi correggere un problema di costi o di qualità che non puoi vedere. La fattura del provider ti dice che martedì hai speso quattro volte più di lunedì. Una trace ti dice quale esecuzione dell'agente ha causato il costo, quale prompt è cresciuto fino a 40,000 token e quale ciclo di retry è stato eseguito nove volte prima di interrompersi. La fattura fornisce il numero. La trace mostra il codice che lo ha prodotto.

In questa guida vengono usati tre termini. Una trace è un'esecuzione completa dell'agente, dall'inizio alla fine. Una observation è un singolo passaggio all'interno di quell'esecuzione: uno span per il codice ordinario, una generation per una chiamata a un modello. Uno score è un numero associato a una trace, ottenuto da una revisione umana o da un valutatore automatico. Langfuse supporta OpenTelemetry (OTel), lo standard indipendente dai vendor per il distributed tracing, quindi la strumentazione già disponibile può inviare i dati a Langfuse.

Cosa esegue realmente Langfuse in modalità self-hosted

Langfuse v4 non è un solo container. È composto da due container applicativi e quattro servizi di storage. Su un singolo VPS, tutti e sei vengono eseguiti sul server.

  • langfuse-web serve l'interfaccia web e l'API di ingestion.
  • langfuse-worker svuota la coda in background. Analizza i batch di ingestion, calcola i costi ed esegue il job notturno di conservazione.
  • Postgres contiene i dati transazionali, come utenti, organizzazioni, progetti, API key e prompt.
  • ClickHouse contiene i dati delle trace, ovvero observations e scores. È un database a colonne progettato per le query analitiche. Per questo una dashboard su oltre cento milioni di righe continua a rispondere rapidamente.
  • Redis gestisce la coda e la cache tra web e worker.
  • MinIO fornisce storage a oggetti compatibile con S3 sul server. Contiene ogni evento raw in ingresso e tutti i file multimediali allegati.

Langfuse pubblica le risorse minime per ogni componente che esegue. Il grafico mostra i tre componenti che svolgono il lavoro.

GraficoLangfuse published minimum resources per component
I dati alla base di questo grafico
[
  {
    "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 richiede da solo 8 GiB di memoria. Il container web e il worker richiedono 4 GiB ciascuno. Questi sono i valori minimi pubblicati per i 3 componenti mostrati nel grafico. La stessa pagina indica 4 GiB per Postgres, 1.5 GiB per Redis o Valkey e 4 GiB per MinIO. Il minimo per tutti e sei i componenti arriva quindi a 25.5 GiB. La guida Docker Compose del progetto raccomanda almeno 4 core, 16 GiB di memoria e circa 100 GiB di storage per una singola macchina. Questo valore è inferiore alla somma dei requisiti minimi dei componenti. Considera quindi 16 GiB come il minimo necessario per un server Compose condiviso, non come margine disponibile.

Non provare a eseguire questa configurazione su un piano da 2 GiB. ClickHouse si avvia e accetta scritture per un certo periodo, poi si arresta durante un merge in background, perché un merge carica in memoria parti di grandi dimensioni di una tabella. Vedrai docker compose ps indicare il container clickhouse come restarting, dmesg contenere una riga simile a Out of memory: Killed process 1234 (clickhouse-serv) e tutte le dashboard di Langfuse restituire 500. Con un carico inferiore ClickHouse rifiuta invece la query e registra DB::Exception: Memory limit (total) exceeded. Il valore su cui pianificare è 16. Se lo stesso VPS deve eseguire anche altri servizi, considera risorse aggiuntive dedicate, perché persino uno stack relativamente leggero come un workspace AFFiNE self-hosted richiede i propri GiB e ClickHouse non ne restituirà nessuno.

Distribuire Langfuse con Docker Compose

Clona il repository. Lo stack, il collegamento tra i servizi e l’ambiente predefinito si trovano tutti nel suo docker-compose.yml.

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

Ogni valore da modificare è contrassegnato con # CHANGEME in quel file. Genera prima i tre secret applicativi.

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

ENCRYPTION_KEY deve essere composto da 256 bit rappresentati da 64 caratteri esadecimali, esattamente ciò che stampa openssl rand -hex 32. Cifra i valori sensibili a riposo, incluse le chiavi dei provider LLM eventualmente memorizzate nell’istanza. Se lo modifichi dopo che esistono già dati, quelle righe non potranno più essere decifrate. Trattalo quindi come permanente fin dal primo avvio. SALT viene usato per calcolare l’hash delle chiavi API di Langfuse. Modificarlo invalida tutte le chiavi già utilizzate dai tuoi agenti.

Imposta quindi POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH e MINIO_ROOT_PASSWORD. La password di MinIO compare in quattro punti: una volta come MINIO_ROOT_PASSWORD e poi come LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY e LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. Se ne ometti uno, MinIO rifiuta quel client con SignatureDoesNotMatch. L’errore compare nel log del worker, mentre l’interfaccia web continua a sembrare funzionante. Conservare questi valori in un file env invece che nel file Compose versionato è il metodo descritto in File env e secret di Docker Compose.

Blocca i tag delle immagini prima di iniziare

Il file fornito usa docker.langfuse.com/langfuse/langfuse:4 e docker.langfuse.com/langfuse/langfuse-worker:4. Questi tag cambiano nel tempo. Langfuse esegue automaticamente all’avvio le migrazioni di Postgres e ClickHouse. Di conseguenza, un normale docker compose pull mesi dopo diventa una migrazione dello schema non pianificata su un database di cui quella mattina non hai eseguito il backup. Blocca entrambe le immagini sulla stessa release in un docker-compose.override.yml. Compose lo applica sopra il file fornito, quindi un successivo git pull non sovrascrive le tue modifiche. Le stesse immagini sono pubblicate su Docker Hub, da cui l’override seguente le scarica.

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

La versione 4.3.1 era la release 4.3 corrente ad agosto 2026. Da allora le release sono state frequenti e v4.56.0 era l’ultima disponibile su GitHub l’11 ottobre 2026. L’override precedente usa v4.72.0, l’ultima disponibile su GitHub al 31 ottobre 2026. Controlla la pagina delle release del progetto su GitHub, blocca la versione corrente il giorno della distribuzione e aggiorna poi quel numero in modo deliberato. Anche alcuni storage image del file fornito richiedono lo stesso trattamento, perché i relativi tag cambiano nel tempo. postgres:17 (il valore predefinito di una variabile POSTGRES_VERSION) e redis:7 seguono una versione principale. Il file fornito usa ora un tag di versione esatto per docker.io/clickhouse/clickhouse-server, bloccando una versione precisa di ClickHouse. Questa regola non riguarda solo Langfuse: un tracker di allenamento openGym self-hosted usa una parte dello stack e richiede comunque un tag git specifico, perché qualsiasi applicazione che migra autonomamente il database all’avvio può trasformare un normale pull in una modifica dello schema.

Avvia lo stack.

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

Il primo avvio esegue le migrazioni. Attendi quindi due o tre minuti prima di verificare la disponibilità dei servizi. Il container web registra Ready nel log quando è pronto. docker compose ps dovrebbe elencare sei servizi nello stato running. Se un container si riavvia continuamente, il relativo log contiene la causa. Le migrazioni di ClickHouse vengono applicate all’avvio del container web. Un valore errato di CLICKHOUSE_MIGRATION_URL compare quindi in docker compose logs langfuse-web, non nel log del worker che stai monitorando. Questa variabile usa il protocollo nativo di ClickHouse sulla porta 9000, non la porta HTTP 8123. Se la punti a 8123, le migrazioni di avvio del container web falliscono. Il worker esegue le migrazioni in background più lente. Il relativo log mostra quindi l’esito di quelle migrazioni.

Controlla lo stato dal server stesso.

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

Una chiamata /api/public/health semplice dimostra solo che il processo API è attivo, perché per impostazione predefinita non verifica il database. La forma failIfDatabaseUnavailable=true è quella da usare per il monitoraggio e restituisce 503 quando il database non è raggiungibile. /api/public/ready restituisce 200 quando il container web è pronto a ricevere traffico e 500 quando gli è stato richiesto di arrestarsi. Entrambi sono normali controlli HTTP. Una pagina di stato di Uptime Kuma può quindi monitorarli e segnalare che lo stack è fuori servizio prima dei tuoi agenti.

Pubblica TLS davanti all’applicazione e chiudi le porte aggiuntive

Il file Compose fornito pubblica 3000:3000 per il container web e 9090:9000 per MinIO. Entrambe le porte sono associate a tutte le interfacce. Su un IP pubblico, chiunque esegua una scansione della porta 3000 raggiunge la pagina di registrazione, mentre chiunque scansioni la porta 9090 accede al bucket che contiene i prompt grezzi.

Una regola del firewall da sola non chiude queste porte. Docker scrive le proprie regole DNAT nella tabella nat, che vengono valutate prima che le regole filter di ufw possano esaminare il pacchetto; di conseguenza, ufw deny 3000 lascia aperta la porta pubblicata. Il problema è abbastanza comune da avere una guida dedicata: perché le porte pubblicate da Docker ignorano ufw. Nel file di override, associa invece le porte all’interfaccia loopback. Usa !override con Docker Compose 2.24.4 o versioni successive per sostituire le porte pubblicate; un semplice elenco esegue il merge con le associazioni originali.

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

NEXTAUTH_URL deve essere l’indirizzo pubblico completo, incluso lo schema, perché il flusso di autenticazione costruisce l’URL di callback a partire da quel valore. Se lo lasci impostato su http://localhost:3000 dietro un proxy HTTPS, il reindirizzamento di accesso invia il browser a un indirizzo che non può raggiungere.

Configura quindi un reverse proxy verso 127.0.0.1:3000 e affidagli la gestione del certificato. Per usare Traefik nello stesso progetto Compose, inoltra le richieste a langfuse-web:3000 tramite la rete Compose, usando le label descritte in eseguire più applicazioni dietro un unico reverse proxy Traefik. Se Langfuse è l’unica applicazione sul server, Caddy svolge lo stesso compito con due righe. Verifica con curl -sI https://langfuse.example.com/api/public/ready, quindi conferma da una seconda macchina che curl http://YOUR_IP:3000 non possa connettersi.

Una precisazione su MinIO. Langfuse distribuisce URL presigned che puntano a quell’endpoint S3, sia agli SDK che caricano contenuti multimediali, sia al browser che li visualizza. Se usi trace multimodali con immagini o audio, un MinIO accessibile soltanto tramite loopback impedisce il caricamento degli allegati da altre macchine e la loro visualizzazione nel browser. Consulta la pagina sulla configurazione del blob storage prima di pubblicarlo tramite proxy, perché l’endpoint inserito nell’URL presigned, LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT, deve corrispondere a quello che pubblichi. Le trace di testo semplice non sono interessate.

Crea il tuo account al primo accesso, quindi impedisci che l’istanza venga registrata da altri. Imposta AUTH_DISABLE_SIGNUP=true dopo aver creato il tuo account, in modo che chiunque raggiunga la pagina non possa registrarsi. Langfuse dispone anche di LANGFUSE_ALLOWED_ORGANIZATION_CREATORS, che limita la possibilità di creare organizzazioni, ma questa funzione è disponibile nell’Enterprise Edition e diventa effettiva solo con una license key. Se stai già usando Authentik come provider di identità, Langfuse supporta una connessione OIDC standard, così gli account vengono gestiti insieme al resto delle applicazioni invece di essere conservati in un elenco di password noto soltanto a questo server.

Invia la prima traccia

Crea un progetto nell'interfaccia web e copia le chiavi pubblica e segreta dalle impostazioni del progetto. L'SDK Python legge tre variabili d'ambiente.

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

LANGFUSE_BASE_URL è il nome della variabile nell'SDK v4, rilasciato a marzo 2026. Il codice e le guide meno recenti usano LANGFUSE_HOST. Se le tracce arrivano su Langfuse Cloud invece che sul tuo server, la causa è l'URL di base non impostato, perché il valore predefinito punta all'istanza ospitata.

L'SDK Python v5 attuale richiede Python 3.11 o versioni successive e Langfuse self-hosted v4.59.0 o versioni successive. La versione del server indicata sopra soddisfa questo requisito.

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()

Il decorator @observe apre un'osservazione attorno alla funzione, acquisisce i relativi argomenti e valore restituito e la annida nell'osservazione già attiva, se presente. AnthropicInstrumentor è la strumentazione OpenTelemetry per il client Anthropic e trasforma ogni chiamata messages.create in una generazione che contiene il nome del modello, l'utilizzo dei token e la latenza, senza modificare il punto della chiamata.

Due chiamate eseguono i controlli al posto tuo. langfuse.auth_check() restituisce False in caso di chiavi non valide o URL di base errato. È più rapido che chiedersi perché la dashboard sia vuota. langfuse.flush() attende l'invio degli span accodati. È necessario nei processi di breve durata, perché l'SDK raggruppa gli span in background e uno script che termina subito porta con sé il batch non ancora inviato. Se un intero team invia tracce invece di un singolo script, imposta una volta sola queste tre variabili nel gateway attraverso cui passano già gli agenti di tutti, anziché nella shell di ogni persona. È così che un harness OneCLI self-hosted mantiene strumentizzate le esecuzioni di tutti i colleghi, lasciando le chiavi in un unico punto.

Perché ClickHouse continua a crescere?

Le tracce sono i dati che, per la maggior parte delle installazioni self-hosted, crescono più rapidamente. Ogni esecuzione dell'agent scrive una riga per ogni passaggio e input e output vengono memorizzati per intero. Di conseguenza, un agent loquace con prompt lunghi produce molti più byte al giorno rispetto all'applicazione che monitora. Se non intervieni, ClickHouse riempie il disco. Quando il disco è pieno, l'acquisizione dei dati si interrompe invece di rallentare.

In questo caso crescono due elementi distinti e servono due correzioni diverse.

Il primo elemento sono i dati delle tue tracce. La correzione consiste nell'impostare la conservazione. In un'istanza self-hosted, la conservazione dei dati è una funzionalità di Enterprise Edition e richiede una chiave di licenza. Senza licenza, Langfuse conserva indefinitamente tracce, osservazioni, punteggi e file multimediali. Devi quindi dimensionare il disco di conseguenza e affidarti all'alert sul disco descritto alla fine di questa sezione. Con una licenza, i proprietari dei progetti e gli amministratori aprono le impostazioni del progetto e impostano un periodo di conservazione dei dati espresso in giorni. Langfuse accetta un minimo di 3 giorni. Ogni notte un job seleziona le tracce, le osservazioni, i punteggi e gli asset multimediali più vecchi di questo intervallo e li elimina da ClickHouse e dallo storage a oggetti, ad eccezione dei file multimediali associati agli elementi dei dataset salvati. Il job richiede il permesso DeleteObject sul bucket, già disponibile per le credenziali root di MinIO presenti nel file compose predefinito. L'eliminazione è permanente. Configura quindi prima un'esportazione verso lo storage a oggetti se ti serve conservare la cronologia a lungo termine. Non scrivere manualmente clausole TTL nelle tabelle gestite da Langfuse. È il job di conservazione a mantenere sincronizzati ClickHouse e il bucket, mentre un TTL manuale elimina i dati soltanto da uno dei due lati.

Scegli l'intervallo in base all'uso effettivo. Le verifiche dei costi e della qualità vengono eseguite su dati vecchi di alcuni giorni, non di mesi. Trenta giorni sono un punto di partenza ragionevole per un team piccolo. 14 giorni sono sufficienti se apri una traccia solo quando si verifica un problema.

Il secondo elemento sono le tabelle dei log di sistema di ClickHouse. Questo aspetto sorprende molti utenti, perché il disco continua a riempirsi anche dopo aver configurato la conservazione. ClickHouse scrive trace_log, text_log, opentelemetry_span_log, metric_log, asynchronous_metric_log e latency_log per la propria diagnostica. Queste tabelle non hanno un TTL predefinito e Langfuse non le legge. Prima individua dove è stato realmente utilizzato lo spazio sul disco.

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
)

Eseguilo con docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD". Se le tabelle di sistema sono ai primi posti nell'elenco, disabilitale con un overlay di configurazione. All'avvio, infatti, ClickHouse unisce ogni file presente in /etc/clickhouse-server/config.d/ alla configurazione principale.

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

Monta il file e riavvia ClickHouse.

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

In questo modo interrompi le nuove scritture. Le righe già presenti sul disco restano lì. Recupera quindi esplicitamente lo spazio con DROP TABLE IF EXISTS system.trace_log e ripeti la stessa operazione per ogni tabella rimossa. Se preferisci conservare la diagnostica, l'alternativa consiste nell'impostare un TTL aggressivo su ogni tabella invece di usare remove="1", come descritto nella documentazione sullo scaling di Langfuse. Queste direttive TTL vengono applicate soltanto quando una tabella di sistema viene creata per la prima volta. In un'installazione esistente, la stessa documentazione spiega anche come applicarle retroattivamente alle tabelle.

È utile conoscere un'altra tabella. blob_storage_file_log tiene traccia dei file degli eventi caricati nel bucket. Se imposti anche una policy del ciclo di vita sul bucket, assegna alla tabella un TTL corrispondente per evitare che le due configurazioni divergano.

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

Configura anche un semplice alert df -h sul disco che contiene i dati. Le tracce non crescono in modo uniforme. La crescita può verificarsi il giorno in cui distribuisci un nuovo agent. Il primo segnale non dovrebbe essere un errore durante l'acquisizione dei dati.

Eseguire il backup di Postgres e ClickHouse

Un backup di Langfuse comprende tre parti. Postgres contiene utenti, organizzazioni, progetti e chiavi API. ClickHouse contiene le tracce. MinIO contiene gli eventi grezzi. Se ripristinate solo Postgres, ottenete un accesso funzionante ma nessuna cronologia. Se ripristinate solo ClickHouse, ottenete una cronologia che nessuno può consultare perché non può effettuare l'accesso. Questa separazione non è specifica di Langfuse. Anche un help desk self-hosted Chatwoot ha la stessa struttura: un dump di Postgres eseguito senza la directory degli upload ripristina conversazioni i cui allegati sono completamente assenti.

Postgres è un semplice pg_dump, come indicato nella documentazione di backup di Langfuse per un'installazione Docker.

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

ClickHouse richiede maggiore attenzione, perché copiare una directory dati mentre sono in esecuzione operazioni di merge non produce un backup coerente. Su un singolo host, l'approccio più semplice consiste nell'arrestare il container e archiviare il volume.

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

Usate il nome del volume mostrato da docker volume ls, non quello scritto nel file YAML. Il file dichiara langfuse_clickhouse_data e Compose aggiunge il nome del progetto come prefisso, quindi un clone in una directory chiamata langfuse produce langfuse_langfuse_clickhouse_data. Se sbagliate, docker run crea un nuovo volume vuoto senza segnalare errori e l'archivio non contiene nulla.

Langfuse carica i dati degli eventi grezzi nel bucket a ogni richiesta di ingestion e li legge nuovamente per ritentare i job di ingestion non riusciti. Per questo, un breve arresto di ClickHouse significa soprattutto che il worker ritenterà in seguito. Eseguite l'operazione in un'ora di bassa attività e mantenetela breve. Per un'istanza più trafficata, l'istruzione BACKUP DATABASE default TO S3(...) di ClickHouse crea un backup coerente senza arrestare il server. MinIO è il terzo componente: mc mirror o la replica MinIO verso un bucket esterno al server lo coprono. Qualunque soluzione produciate, trasferitela fuori dal server: è questo lo scopo dei backup restic cifrati su un VPS.

Redis contiene la coda e la cache. La sua perdita elimina i job accodati, anche quando i relativi file degli eventi grezzi restano nel bucket.

Il problema della coerenza è reale e va espresso chiaramente. Postgres e ClickHouse vengono scaricati in momenti diversi, quindi un ripristino può lasciare una riga di progetto senza tracce oppure tracce appartenenti a un progetto che non esiste più. Langfuse tollera questa situazione, ma eseguite i due dump a breve distanza l'uno dall'altro e in una finestra di bassa attività. Il bucket degli eventi è la vera rete di sicurezza, perché Langfuse vi carica i dati degli eventi grezzi a ogni richiesta di ingestion.

Eseguite almeno una volta il ripristino in uno stack di test. In questo modo potete scoprire subito un nome di volume errato, invece di farlo durante un'interruzione del servizio.

Cosa controllare per prima cosa

Quattro elementi sono indispensabili nella prima settimana.

  • Costo per trace. Langfuse calcola il costo dal nome del modello e dall'utilizzo dei token. Ordina quindi i trace per costo e leggi dall'inizio alla fine quello più costoso. Di solito la causa è un prompt diventato troppo grande: un intero documento incollato nel contesto oppure una cronologia della conversazione che nessuno riduce. Quando il problema è visibile, controllare quanto costa un agente AI diventa un'attività di progettazione invece di una stima.
  • Utilizzo dei token separato tra input e output. I token di input sono numerosi e poco costosi, quelli di output sono pochi e costosi, mentre gli input memorizzati nella cache costano ancora meno. La stessa contabilità è descritta in come viene conteggiato l'utilizzo dei token in Claude Code e si applica a qualsiasi agente scritto autonomamente.
  • Percentili di latenza. La mediana nasconde il problema. I timeout si verificano nei valori p95 e p99. All'interno di un ciclo dell'agente, inoltre, una chiamata lenta a uno strumento al valore p95 viene moltiplicata per il numero di iterazioni.
  • Chiamate agli strumenti non riuscite. Filtra le osservazioni per livello ERROR. Uno strumento che fallisce nel 5% dei casi non emerge in un tasso aggregato di successo, ma è evidente nei trace, dove puoi osservare il modello riprovare e consumare token per aggirare il problema.

Imposta il periodo di conservazione e scegli la dashboard che controllerai ogni settimana, nello stesso giorno del deployment. Uno strumento di osservabilità che nessuno apre è un database che finisce per riempire un disco.

FAQ

Quanta memoria richiede un'istanza self-hosted di Langfuse?

Prevedi 4 core CPU e 16 GiB di memoria, come raccomandato dalla guida Langfuse Docker Compose per una singola macchina virtuale, oltre a circa 100 GiB di spazio di archiviazione. I requisiti minimi pubblicati per i componenti sono 8 GiB per ClickHouse e 4 GiB ciascuno per i container web e worker. La stessa pagina indica 4 GiB per Postgres, 1.5 GiB per Redis e 4 GiB per MinIO. Il totale dei sei componenti è quindi 25.5 GiB, superiore ai 16 GiB raccomandati per Compose.

Perché il disco di ClickHouse continua a riempirsi dopo aver configurato la conservazione dei dati?

L'impostazione della conservazione si applica solo ai dati gestiti direttamente da Langfuse. ClickHouse scrive separatamente le proprie tabelle diagnostiche trace_log, text_log, opentelemetry_span_log, metric_log, asynchronous_metric_log e latency_log, che non hanno un TTL predefinito. Esegui system.parts raggruppando i risultati per tabella per individuare quella più grande. Disabilita quindi le tabelle non utilizzate con una voce remove="1" in un file sotto /etc/clickhouse-server/config.d/, riavvia ClickHouse ed elimina le tabelle esistenti per recuperare lo spazio già utilizzato.

Qual è il periodo minimo di conservazione dei dati in Langfuse?

Tre giorni. La conservazione viene configurata per progetto nelle impostazioni del progetto oppure tramite l'Organization Management API. Un job notturno elimina da ClickHouse e dal blob storage le traces, le observations, gli scores e gli asset multimediali più vecchi del periodo configurato, ad eccezione dei media associati agli elementi salvati dei dataset. In un'istanza self-hosted, questa funzione è disponibile nell'Enterprise Edition e richiede una license key. Senza una license key, i dati vengono conservati indefinitamente. L'eliminazione non può essere annullata. Configura quindi prima un'esportazione verso il blob storage se devi conservare la cronologia oltre questo periodo.

Devo eseguire il backup sia di Postgres sia di ClickHouse?

Sì, perché contengono dati diversi. Postgres contiene utenti, organizzazioni, progetti e API key. ClickHouse contiene invece i dati delle traces. Un ripristino del solo Postgres produce un'istanza a cui puoi accedere, ma che non contiene dati applicativi. Esegui il backup anche del bucket MinIO, perché contiene gli eventi raw che Langfuse conserva al momento della ricezione. Nel contesto dello stack, è l'elemento più vicino a una source of truth.

Posso collegare una configurazione OpenTelemetry esistente a un'istanza self-hosted di Langfuse?

Sì. Langfuse v4 e i relativi SDK attuali sono basati su OpenTelemetry, mentre le instrumentation OTel per Anthropic e OpenAI esportano direttamente verso Langfuse. In Python, esegui pip install langfuse opentelemetry-instrumentation-anthropic, chiama AnthropicInstrumentor().instrument() una volta all'avvio e imposta LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY e LANGFUSE_BASE_URL sull'host desiderato. Verifica il risultato con langfuse.auth_check() prima di cercare il problema in una dashboard mancante.

Questo articolo ti è stato utile?