Shutdown: MUST call await shutdown() before exit to flush queues.
💡 Best Practices (Patterns)
Environment Variables: Prefer ENV vars (SELFSHIP_ORG_ID, SELFSHIP_ENV) over hardcoding credentials in init().
Graceful Exit: Always wire await selfship.shutdown() to SIGTERM/SIGINT to prevent data loss from pending background batches.
Session Threading: Pass conversationId in begin()/track() to reliably group LLM calls by chat session.
Auto-instrumentation: Wrap core generation methods with observe(asyncFn, { name }) to trace inputs/outputs seamlessly without cluttering business logic.
Global Identity Context: Use identify(userId, traits) once per user to automatically inject { user: traits } metadata into all future traces for that ID.
Explicit Failure: Pass success: false to Interaction.end() to correctly flag the span as an ERROR with a failed status message.
🚨 Gotchas / Warnings (Anti-patterns)
OOM Memory Leak:identify() stores traits in a perpetual, unevicted memory Map. Do NOT use for millions of unique users in long-running Node/Bun servers; it will leak memory.
Environment Rejection:SELFSHIP_ENV strictly forbids prefixes like langfuse and must be <=40 chars ([a-z0-9-_]+). Invalid envs silently fallback to "development".
Unflushed Exits: Process death without await shutdown() loses pending background traces (due to inherited Langfuse batching).
init() Race Conditions: Calling begin(), track(), or observe() before init() synchronously throws an initialization error.
Span vs Trace Asymmetry:begin() creates both a Trace and a Span. track()only creates a Trace. Do not expect Spans in the UI from track().