SSD Nodes Learn 🎉 VPS החל מ־$5.50/חודש
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-13

אירוח עצמי של Langfuse: מדריך מלא ל-VPS

למדו כיצד להריץ Langfuse באופן עצמאי על שרת VPS. המדריך כולל הגדרות TLS, ניהול זיכרון ב-ClickHouse, שימוש בתגיות Docker קבועות וביצוע גיבויים תקינים למניעת אובדן נתונים.

למה בכלל לבצע מעקב (trace) אחר סוכן AI

אתם מארחים את Langfuse באופן עצמאי כדי לראות מה הסוכן שלכם באמת עשה במהלך הרצה. Langfuse הוא כלי בקוד פתוח לניטור (observability) של מודלי שפה גדולים (LLM). הוא מתעד כל prompt, כל תגובה של המודל, כל קריאה לכלי וכל token, ולאחר מכן מקבץ אותם תחת trace אחד שניתן לפתוח ולקרוא. הרצת הכלי על גבי ה-VPS שלכם מבטיחה שה-prompts הללו לעולם לא עוזבים שרת שנמצא בשליטתכם.

הסיבה להשקיע בכך ברורה. לא ניתן לתקן בעיית עלות או בעיית איכות שאינכם יכולים לראות. חשבונית מספק השירות תגיד לכם שיום שלישי עלה פי ארבעה מיום שני. ה-trace יגיד לכם איזו הרצה של הסוכן גרמה לכך, איזה prompt תפח ל-40,000 tokens, ואיזו לולאת ניסיונות חוזרים (retry loop) רצה תשע פעמים לפני שוויתרה. החשבונית נותנת לכם את המספר. ה-trace נותן לכם את הקוד שיצר אותו.

במדריך זה נעשה שימוש בשלושה מונחים. trace הוא הרצה מקצה לקצה של הסוכן שלכם. observation הוא צעד בודד בתוך אותה הרצה: span עבור קוד רגיל, או generation עבור קריאה למודל. score הוא מספר המוצמד ל-trace, שניתן על ידי סקירה אנושית או מעריך אוטומטי. Langfuse תומך ב-OpenTelemetry (OTel), התקן הניטרלי לניטור מבוזר, כך שכל כלי אינסטרומנטציה שכבר קיים אצלכם יכול להצביע עליו.

מה מריץ אירוח עצמי של Langfuse בפועל

Langfuse v4 אינו מכולה אחת. הוא מורכב משתי מכולות יישום וארבעה שירותי אחסון, ועל שרת VPS יחיד, כל השישה רצים על המכונה שלכם.

  • langfuse-web מגיש את ממשק האינטרנט ואת ה-API לקליטת נתונים.
  • langfuse-worker מרוקן את התור ברקע. הוא מנתח אצוות קליטה, מחשב עלויות ומריץ את משימת שמירת הנתונים הלילית.
  • Postgres מחזיק נתונים טרנזקציוניים כגון משתמשים, ארגונים, פרויקטים, מפתחות API והנחיות (prompts).
  • ClickHouse מחזיק את נתוני ה-trace עצמם, כלומר תצפיות וציונים. זהו בסיס נתונים טורי (column store) שנבנה עבור שאילתות אנליטיות, וזו הסיבה שלוח בקרה המציג מאה מיליון שורות עדיין מגיב במהירות.
  • Redis משמש כתור וכמטמון (cache) שנמצא בין ה-web לבין ה-worker.
  • MinIO מספק אחסון אובייקטים תואם S3 על השרת. הוא מחזיק כל אירוע גולמי נכנס בתוספת כל מדיה שתצרפו.

Langfuse מפרסם את דרישות המשאבים המינימליות עבור שלושת הרכיבים שמבצעים את העבודה.

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 לבדו דורש 8 GiB של זיכרון. מכולת ה-web ומכולת ה-worker דורשות 4 GiB כל אחת. אלו הם הרף המינימלי שפורסם עבור 3 הרכיבים ש-Langfuse מגדיר, ועדיין יש צורך בזיכרון נוסף עבור Postgres, Redis ו-MinIO. מדריך ה-Docker Compose של הפרויקט עצמו ממליץ על מכונה עם 4 ליבות, 16 GiB של זיכרון וכ-100 GiB של אחסון, מה שתואם את החישוב הזה במקום להוסיף לו נפח מיותר.

אל תנסו זאת על תוכנית של 2 GiB. ClickHouse עולה, מקבל כתיבות למשך זמן מה, ואז קורס במהלך מיזוג רקע (background merge), מכיוון שמיזוג טוען חלקים גדולים מהטבלה לזיכרון. אתם תראו את docker compose ps מדווח על מכולת ה-clickhouse כ-restarting, את dmesg מכיל שורה כמו Out of memory: Killed process 1234 (clickhouse-serv), וכל לוח בקרה של Langfuse יחזיר שגיאת 500. תחת עומס קל יותר, ClickHouse מסרב לבצע את השאילתה ומתעד DB::Exception: Memory limit (total) exceeded. שמונה GiB הם ברי-ביצוע עבור מפתח יחיד ששולח כמה אלפי traces ביום. שש-עשרה הוא המספר שכדאי לתכנן עבורו.

פריסת Langfuse באמצעות Docker Compose

שכפלו את המאגר. ה-stack, החיבורים והגדרות הסביבה המוגדרות כברירת מחדל נמצאים כולם בתוך ה-docker-compose.yml שלו.

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

כל ערך שעליכם לשנות מסומן ב-# CHANGEME בתוך הקובץ. תחילה, צרו את שלושת ה-secrets של היישום.

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

הערך ENCRYPTION_KEY חייב להיות באורך 256 ביט, כתוב כ-64 תווים הקסדצימליים, וזה בדיוק מה ש-openssl rand -hex 32 מדפיס. הוא מצפין ערכים רגישים במצב מנוחה (at rest), כולל כל מפתחות ספקי ה-LLM שתאחסנו במופע. שינוי שלו לאחר שקיימים נתונים יגרום לכך שלא ניתן יהיה לפענח את השורות הללו, לכן התייחסו אליו כקבוע החל מה-boot הראשון. ה-SALT משמש לביצוע hashing למפתחות ה-API של Langfuse שלכם, לכן שינוי שלו יבטל את התוקף של כל מפתח שהסוכנים שלכם כבר משתמשים בו.

לאחר מכן, הגדירו את POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH ו-MINIO_ROOT_PASSWORD. סיסמת ה-MinIO מופיעה בארבעה מקומות: פעם אחת כ-MINIO_ROOT_PASSWORD, ולאחר מכן שוב כ-LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY ו-LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. אם תפספסו אחד, MinIO ידחה את ה-client עם השגיאה SignatureDoesNotMatch, שתופיע בלוג של ה-worker בעוד שממשק ה-web ייראה תקין. שמירת ערכים אלו בקובץ env במקום בקובץ ה-compose המנוהל ב-git היא התבנית המתוארת ב-קבצי env ו-secrets ב-Docker Compose.

קיבוע גרסאות ה-image לפני תחילת העבודה

הקובץ שמגיע עם התוכנה משתמש ב-langfuse/langfuse:4 וב-langfuse/langfuse-worker:4. תגיות אלו משתנות. Langfuse מריצה את ה-migrations של Postgres ו-ClickHouse באופן אוטומטי בעת העלייה, לכן פקודת docker compose pull שגרתית חודשים לאחר מכן עלולה להפוך ל-schema migration לא מתוכנן על מסד נתונים שלא גיביתם באותו בוקר. קבעו את שניהם לגרסה אחת בתוך docker-compose.override.yml, ש-Compose ימזג מעל הקובץ המקורי, כך שפקודת git pull עתידית לעולם לא תדרוס את השינויים שלכם.

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

גרסה 4.3.1 הייתה גרסת ה-4.3 העדכנית נכון לאוגוסט 2026 (גרסה 4.4.0 שוחררה מאז). בדקו את דף ה-releases ב-GitHub של הפרויקט, קבעו את הגרסה העדכנית ביום הפריסה, ולאחר מכן עדכנו את המספר באופן יזום. ה-images של האחסון בקובץ המקורי כבר מקובעים לגרסאות major, כגון postgres:17, clickhouse-server:25.12 ו-redis:7, והם ראויים לאותו יחס.

העלו את המערכת.

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

ה-boot הראשון מריץ את ה-migrations, לכן המתינו דקה או שתיים לפני שאתם מצפים לתגובה. הפקודה docker compose ps אמורה להציג שישה שירותים במצב running. אם ה-worker מבצע restart בלולאה, הלוג שלו יכיל את הסיבה: CLICKHOUSE_MIGRATION_URL משתמש בפרוטוקול ה-native של ClickHouse בפורט 9000, ולא בפורט ה-HTTP 8123. הפנייה שלו ל-8123 תיכשל, בעוד שה-container של ה-web ייראה תקין.

בדקו את תקינות המערכת מהשרת עצמו.

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

קריאת /api/public/health פשוטה רק מוכיחה שתהליך ה-API פעיל, כיוון שהיא מדלגת במכוון על מסד הנתונים כדי שהשירות ימשיך להגיב בזמן ש-Postgres חווה הפרעה רגעית. הפורמט failIfDatabaseUnavailable=true הוא זה שכדאי להפנות אליו כלי ניטור, והוא מחזיר 503 כאשר מסד הנתונים אינו נגיש. ה-/api/public/ready מחזיר 200 ברגע שה-migrations הסתיימו וה-container מוכן לקבל תעבורה. שניהם בדיקות HTTP רגילות, לכן דף סטטוס ב-Uptime Kuma יכול לנטר אותם ולהתריע שה-stack למטה לפני שהסוכנים שלכם יבחינו בכך.

הצבת TLS בחזית וסגירת פורטים מיותרים

קובץ ה-compose שמגיע עם התוכנה מפרסם את 3000:3000 עבור ה-container של ה-web ואת 9090:9000 עבור MinIO. שניהם מאזינים לכל ממשקי הרשת. בכתובת IP ציבורית, המשמעות היא שכל מי שסורק את פורט 3000 יגיע לדף ההרשמה שלכם, וכל מי שסורק את 9090 יתקשר ישירות ל-bucket שבו מאוחסנים ה-prompts הגולמיים שלכם.

חוק firewall לבדו לא יסגור אותם. Docker כותב חוקי DNAT משלו לטבלת ה-nat, והם מוערכים לפני שחוקי ה-filter של ufw בכלל רואים את החבילה, לכן ufw deny 3000 משאיר את הפורט המפורסם פתוח. זו בעיה נפוצה מספיק כדי שיהיה לה מדריך משלה: מדוע פורטים שמפורסמים על ידי Docker עוקפים את ufw. הגדירו האזנה ל-loopback בלבד בקובץ ה-override שלכם במקום זאת.

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 חייב להיות הכתובת הציבורית המדויקת, כולל ה-scheme, כיוון שתהליך ההתחברות בונה את ה-callback URL מתוך ערך זה. אם תשאירו אותו כ-http://localhost:3000 מאחורי proxy מסוג HTTPS, סבב ההתחברות ישלח את הדפדפן לכתובת שהוא לא יכול להגיע אליה.

כעת כוונו reverse proxy אל 127.0.0.1:3000 ותנו לו לנהל את התעודה. Traefik באותו פרויקט Compose הוא הבחירה המקובלת, ותוויות הניתוב הן אלו המכוסות ב-הרצת מספר יישומים מאחורי reverse proxy אחד של Traefik. Caddy מבצע את אותה עבודה בשתי שורות אם Langfuse הוא השירות היחיד על השרת. ודאו זאת באמצעות curl -sI https://langfuse.example.com/api/public/ready, ולאחר מכן אשרו ממכונה אחרת ש-curl http://YOUR_IP:3000 אכן מחזיר כעת timeout.

הסתייגות אחת לגבי MinIO: Langfuse מגיש מדיה מצורפת לדפדפן שלכם דרך presigned URLs שמצביעים על ה-endpoint של ה-S3. לכן, אם אתם משתמשים ב-traces מולטי-מודאליים הכוללים תמונות או אודיו, הגדרת MinIO ל-loopback בלבד תגרום לכך שהקבצים המצורפים לא ייטענו. קראו את דף הגדרות ה-blob storage לפני שאתם מציבים אותו מאחורי proxy, כיוון שה-endpoint שנכתב בתוך ה-presigned URL חייב להתאים למה שאתם מפרסמים. traces של טקסט בלבד אינם מושפעים מכך.

צרו את החשבון שלכם בביקור הראשון, ולאחר מכן שמרו על המופע שלכם פרטי. הגדירו את LANGFUSE_ALLOWED_ORGANIZATION_CREATORS לכתובת האימייל שלכם, כך שזר שיגיע לדף לא יוכל ליצור ארגון על השרת שלכם. אם אתם כבר מריצים את Authentik כספק הזהות שלכם, Langfuse מקבל חיבור OIDC סטנדרטי, כך שחשבונות מנוהלים יחד עם שאר היישומים שלכם במקום להיות רשומים ברשימת סיסמאות שרק שרת זה מכיר.

שליחת ה-trace הראשון שלך

צור פרויקט בממשק האינטרנט והעתק את מפתחות ה-public וה-secret שלו מהגדרות הפרויקט. ה-SDK של Python קורא שלושה משתני סביבה.

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

LANGFUSE_BASE_URL הוא שם המשתנה ב-SDK גרסה v4, אשר שוחרר במרץ 2026. קוד ישן ומדריכים ישנים משתמשים ב-LANGFUSE_HOST. אם ה-traces שלך מגיעים ל-Langfuse Cloud במקום לשרת שלך, הסיבה היא משתנה base URL שלא הוגדר, כיוון שברירת המחדל מצביעה על המופע המנוהל (hosted instance).

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

ה-decorator בשם @observe פותח תצפית (observation) סביב הפונקציה, לוכד את הארגומנטים שלה ואת ערך ההחזרה שלה, ומקנן אותה תחת כל תצפית שכבר פעילה. AnthropicInstrumentor הוא ה-instrumentation של OpenTelemetry עבור ה-client של Anthropic, והוא הופך כל קריאת messages.create ל-generation הנושאת את שם המודל, את ניצול ה-tokens ואת ה-latency, ללא כל שינוי באתר הקריאה.

שתי קריאות מבצעות את הבדיקה עבורך. langfuse.auth_check() מחזירה False במקרה של מפתחות שגויים או base URL לא תקין, וזה מהיר יותר מאשר לתהות מדוע ה-dashboard ריק. langfuse.flush() חוסמת את התהליך עד לשליחת ה-spans שבתור; תהליכים בעלי זמן חיים קצר זקוקים לה, כיוון שה-SDK מבצע batching ברקע, וסקריפט שמסתיים באופן מיידי לוקח איתו את ה-batch שלא נשלח.

מדוע נפח הנתונים ב-ClickHouse ממשיך לגדול?

עקבות (traces) הם סוג הנתונים שגדל בקצב המהיר ביותר ברוב המערכות המנוהלות עצמאית. כל הרצה של סוכן (agent) כותבת שורה אחת לכל שלב, והקלט והפלט נשמרים במלואם; לכן, סוכן "פטפטן" עם הנחיות (prompts) ארוכות מייצר הרבה יותר בתים ביום מאשר היישום שהוא מנטר. אם לא מטפלים בכך, ClickHouse ממלא את הדיסק, ודיסק מלא עוצר את קליטת הנתונים במקום להאט אותה.

שני גורמים נפרדים גורמים לגדילה הזו, והם דורשים שני פתרונות נפרדים.

הראשון הוא נתוני העקבות שלכם, והפתרון הוא הגדרת תקופת שמירה (retention). פתחו את הגדרות הפרויקט בממשק האינטרנט והגדירו תקופת שמירת נתונים בימים. Langfuse מקבלת מינימום של 3 ימים. משימה לילית בוחרת עקבות, תצפיות, ציונים ונכסי מדיה ישנים יותר מחלון זמן זה ומוחקת אותם מ-ClickHouse ומאחסון ה-blob. המשימה זקוקה להרשאת DeleteObject על ה-bucket, הרשאה שכבר קיימת בפרטי הגישה של ה-root ב-MinIO בקובץ ה-compose המוגדר כברירת מחדל. המחיקה היא לצמיתות, לכן הגדירו ייצוא לאחסון blob לפני כן אם אתם זקוקים להיסטוריה לטווח ארוך. אל תכתבו ידנית פקודות TTL על הטבלאות של Langfuse: משימת השמירה היא זו שמתאמת בין ClickHouse לבין ה-bucket, ומחיקת TTL ידנית תמחק נתונים מצד אחד בלבד.

בחרו את חלון הזמן לפי השימוש בפועל. בחינת עלויות ואיכות מתבצעת על נתונים בני ימים ספורים, לא חודשים. 30 ימים הם נקודת התחלה סבירה לצוות קטן, ו-14 ימים מספיקים אם אתם פותחים עקבות רק כאשר משהו משתבש.

הגורם השני הוא טבלאות הלוגים של המערכת ב-ClickHouse, וזה מפתיע אנשים, כיוון שהדיסק ממשיך לגדול גם לאחר הגדרת תקופת השמירה. ClickHouse כותב את trace_log, text_log, opentelemetry_span_log, metric_log ו-asynchronous_metric_log לצורכי אבחון עצמי; הם מגיעים ללא TTL, ו-Langfuse לעולם לא קוראת אותם. ראשית, בדקו לאן הלך שטח הדיסק בפועל.

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
)

הריצו זאת עם docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD". אם טבלאות המערכת נמצאות בראש הרשימה, כבו אותן באמצעות config overlay, כיוון ש-ClickHouse ממזג כל קובץ ב-/etc/clickhouse-server/config.d/ מעל קובץ התצורה הראשי שלו בעת העלייה.

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

בצעו mount לקובץ והפעילו מחדש את ClickHouse.

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

זה עוצר כתיבות חדשות. שורות שכבר נמצאות על הדיסק יישארו שם, לכן פנו את השטח במפורש באמצעות DROP TABLE IF EXISTS system.trace_log ועשו זאת עבור כל טבלה שהסרתם. אם אתם מעדיפים לשמור את נתוני האבחון, החלופה היא הגדרת TTL אגרסיבי לכל טבלה במקום remove="1", כפי שמפורט בתיעוד ה-scaling של Langfuse.

כדאי להכיר טבלה נוספת. blob_storage_file_log עוקבת אחר קובצי האירועים שהועלו ל-bucket שלכם. אם הגדרתם מדיניות מחזור חיים (lifecycle policy) על ה-bucket, הגדירו לטבלה TTL תואם כדי שהשניים לא יסטו זה מזה.

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

הגדירו התראה פשוטה מסוג df -h גם על דיסק הנתונים. עקבות אינם גדלים בצורה חלקה. הם גדלים ביום שבו אתם משיקים סוכן חדש, והסימן הראשון לכך לא צריך להיות כשל בקליטת הנתונים.

גיבוי Postgres ו-ClickHouse

גיבוי של Langfuse מורכב משלושה חלקים. Postgres מאחסן את המשתמשים, הארגונים, הפרויקטים ומפתחות ה-API שלכם. ClickHouse מאחסן את ה-traces. MinIO מאחסן את ה-events הגולמיים. שחזור של Postgres בלבד יאפשר לכם להתחבר למערכת, אך ללא היסטוריה. שחזור של ClickHouse בלבד יציג היסטוריה, אך אף משתמש לא יוכל להתחבר כדי לצפות בה.

Postgres הוא pg_dump רגיל, וזהו הפתרון המומלץ בתיעוד הגיבוי של Langfuse.

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

ClickHouse דורש תשומת לב רבה יותר, כיוון שהעתקה של ספריית נתונים חיה בזמן שמתבצעים תהליכי מיזוג (merges) אינה מהווה גיבוי עקבי. הגישה הפשוטה בשרת בודד היא לעצור את ה-container ולבצע ארכיון ל-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

השתמשו בשם ה-volume ש-docker volume ls מציג, ולא בשם שכתוב ב-YAML. הקובץ מגדיר langfuse_clickhouse_data, אך Compose מוסיף לו תחילית של שם הפרויקט; לכן, שכפול בתיקייה ששמה langfuse ייצור langfuse_langfuse_clickhouse_data. טעות בשם זה תגרום ל-docker run ליצור volume חדש וריק ללא התראה, והארכיון שלכם יהיה ריק.

ה-container של ה-web כותב כל event נכנס ל-bucket לפני שה-worker מעבד אותו, לכן עצירה קצרה של ClickHouse משמעותה לרוב שה-worker יבצע ניסיונות חוזרים לאחר מכן. בצעו זאת בשעה שקטה ושמרו על העצירה קצרה. עבור מופע עמוס יותר, פקודת ה-BACKUP DATABASE default TO S3(...) של ClickHouse עצמו יוצרת גיבוי עקבי ללא צורך בעצירת השרת. MinIO הוא החלק השלישי, ו-mc mirror או שכפול של MinIO ל-bucket מחוץ לשרת יכסו זאת. לא משנה מה יצרתם, הוציאו את הגיבוי מהשרת; לשם כך נועדו גיבויי restic מוצפנים ב-VPS.

Redis אינו זקוק לגיבוי. הוא מאחסן את התור ואת ה-cache, לכן אובדן שלו משמעותו איבוד ה-events שנמצאים כרגע בתהליך בלבד, ללא אובדן נתונים ישנים יותר.

סייג העקביות הוא אמיתי וראוי להבהרה. ה-dumps של Postgres ושל ClickHouse מתבצעים ברגעים שונים, לכן שחזור עלול להוביל למצב שבו קיימת שורת פרויקט ללא traces, או traces ששייכים לפרויקט שכבר אינו קיים. Langfuse סובל זאת, אך הקפידו לבצע את שני ה-dumps בסמיכות זמנים ובחלון זמן של תעבורה נמוכה. ה-bucket של ה-events הוא רשת הביטחון האמיתית, כיוון ש-Langfuse שומר בו כל event נכנס לפני עיבודו.

בצעו שחזור לסביבת בדיקות לפחות פעם אחת. כך תגלו טעויות בשמות של volumes כעת, ולא בזמן תקלה.

מה לבדוק תחילה

ארבעה דברים ראויים לתשומת לב בשבוע הראשון.

  • עלות לכל trace. המערכת Langfuse מחשבת עלות לפי שם המודל וצריכת ה-tokens, לכן מומלץ למיין traces לפי עלות ולעבור על היקר ביותר מתחילתו ועד סופו. התשובה היא לרוב prompt שתפח: מסמך שלם שהודבק לתוך ה-context, או היסטוריית שיחה שאף אחד לא מקצץ. ברגע שניתן לראות זאת, שליטה בעלויות של סוכן AI הופכת למשימה הנדסית במקום לניחוש.
  • חלוקת צריכת tokens לפי קלט ופלט. tokens של קלט הם רבים וזולים, tokens של פלט הם מעטים ויקרים, וקלט שנשמר ב-cache זול עוד יותר. אותו חישוב מפורט ב-אופן החישוב של צריכת tokens ב-Claude Code, והוא תקף לכל סוכן שתפתחו בעצמכם.
  • אחוזוני שיהוי (Latency). החציון מסתיר את הבעיה. ה-p95 וה-p99 הם המקומות שבהם נמצאים ה-timeouts, ובתוך לולאת סוכן, קריאת כלי איטית ב-p95 מוכפלת במספר האיטרציות.
  • קריאות כלי שנכשלו. סננו תצפיות לפי רמה ERROR. כלי שנכשל ב-5% מהמקרים אינו מורגש בשיעור הצלחה מצטבר, אך הוא בולט מאוד ב-traces, שם ניתן לראות את המודל מנסה שוב ושוב ומבזבז tokens בניסיון לעקוף את התקלה.

הגדירו את חלון השמירה (retention) ובחרו את ה-dashboard שתבדקו מדי שבוע באותו יום שבו אתם מבצעים פריסה (deploy). כלי ניטור שאף אחד לא פותח הוא בסך הכל מסד נתונים שממלא את הדיסק.

FAQ

כמה זיכרון דרוש להרצה עצמית של Langfuse?

תכננו עבור 4 ליבות CPU ו-16 GiB זיכרון, כפי שמומלץ במדריך ה-Docker Compose של Langfuse עבור מכונה וירטואלית בודדת, בתוספת כ-100 GiB של שטח אחסון. דרישות המינימום שפורסמו לרכיבים הן 8 GiB עבור ClickHouse ו-4 GiB לכל אחד מהקונטיינרים של ה-web וה-worker; בנוסף, Postgres, Redis ו-MinIO דורשים זיכרון משלהם מעבר לכך. 8 GiB מספיקים להרצת מופע עבור מפתח בודד. 2 GiB אינם מספיקים: ה-kernel יסיים את פעולת ה-ClickHouse במהלך מיזוגי רקע, ו-dmesg יציג Out of memory: Killed process.

מדוע הדיסק של ClickHouse ממשיך להתמלא לאחר הגדרת שמירת נתונים (retention)?

הגדרת ה-retention מכסה רק את הנתונים של Langfuse עצמה. ClickHouse כותב בנפרד טבלאות אבחון בשמות trace_log, text_log, opentelemetry_span_log, metric_log ו-asynchronous_metric_log, ואלו מגיעות ללא הגדרת TTL. הריצו את השאילתה system.parts מקובצת לפי טבלה כדי לראות איזו מהן היא הגדולה ביותר, לאחר מכן השביתו את הטבלאות שאינן בשימוש באמצעות רשומה remove="1" בקובץ תחת /etc/clickhouse-server/config.d/, בצעו restart ל-ClickHouse, ומחקו את הטבלאות הקיימות כדי לפנות את השטח שכבר נוצל.

מהי תקופת שמירת הנתונים המינימלית ב-Langfuse?

שלושה ימים. ה-retention מוגדר לכל פרויקט בהגדרות הפרויקט, או דרך ה-API של הפרויקטים, ומשימה לילית מוחקת traces, observations, scores ונכסי מדיה ישנים יותר מהחלון שהוגדר, הן מ-ClickHouse והן מאחסון ה-blob. לא ניתן לבטל מחיקה, לכן הגדירו ייצוא של אחסון ה-blob מראש אם אתם זקוקים להיסטוריה מעבר לחלון זמן זה.

האם עליי לגבות גם את Postgres וגם את ClickHouse?

כן, מכיוון שהם מחזיקים נתונים שונים. Postgres מחזיק משתמשים, ארגונים, פרויקטים ומפתחות API, בעוד ש-ClickHouse מחזיק את נתוני ה-trace עצמם. שחזור של Postgres בלבד ייתן לכם מופע שניתן להתחבר אליו, אך הוא יהיה ריק מתוכן. גבו גם את ה-bucket של MinIO, שכן הוא מחזיק את ה-events הגולמיים ש-Langfuse שומרת עם הגעתם, וזהו המקור הקרוב ביותר ל-"מקור האמת" (source of truth) ב-stack.

האם ניתן להפנות הגדרת OpenTelemetry קיימת ל-Langfuse בהרצה עצמית?

כן. Langfuse בגרסה v4 וה-SDKs שלה בגרסה v4 בנויים על OpenTelemetry, וה-instrumentations של Anthropic ו-OpenAI ב-OTel מייצאים נתונים ישירות אליה. ב-Python, הריצו את pip install langfuse opentelemetry-instrumentation-anthropic, קראו ל-AnthropicInstrumentor().instrument() פעם אחת בעת העלייה, והגדירו את LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY ו-LANGFUSE_BASE_URL למארח שלכם. אשרו את התקינות עם langfuse.auth_check() לפני שתתחילו לחפש dashboard חסר.