Memory Management
Vestig is designed for memory efficiency in high-volume production environments. This guide covers internal memory patterns and best practices for avoiding leaks.
Architecture Overview
Vestig uses several memory-aware patterns:
| Component | Pattern | Purpose |
|---|---|---|
| Child loggers | WeakRef + FinalizationRegistry |
Allow GC of unused child loggers |
| Transport buffers | CircularBuffer |
Bounded memory for log batching |
| Context storage | AsyncLocalStorage |
Request-scoped, auto-cleaned |
| Error serialization | Depth limits | Prevent unbounded recursion |
Child Logger Memory Management
WeakRef Caching
Child loggers are cached using WeakRef, allowing garbage collection when no longer referenced:
FinalizationRegistry Cleanup
Vestig uses FinalizationRegistry to clean up cache entries when child loggers are collected:
Avoiding Cache Pollution
CircularBuffer
Bounded Memory for Batching
The CircularBuffer ensures transport buffers don't grow unboundedly:
onDrop Callback
Handle dropped entries for monitoring or backup:
Buffer Sizing
Choose buffer size based on:
Transport Memory Patterns
BatchTransport Buffering
Batch transports maintain an internal buffer:
Flush Before High-Memory Operations
Transport Cleanup
Always destroy transports on shutdown:
Context Memory
AsyncLocalStorage Lifecycle
Context is automatically cleaned when async operations complete:
Avoiding Context Leaks
Error Serialization Memory
Depth Limits
Error cause chains are limited to prevent memory issues:
Circular Reference Handling
Circular errors are detected and stopped:
High-Volume Patterns
Sampling to Reduce Memory Pressure
Streaming Large Metadata
Async Iterator for File Transport
For very high volume, consider streaming:
Monitoring Memory Usage
Log Buffer Metrics
Memory Profiling
Best Practices Summary
Do
- Use
logger.child(name, { context })for dynamic data (not cached) - Call
logger.destroy()on shutdown - Configure appropriate
batchSizeandflushInterval - Use sampling for high-volume environments
- Log summaries of large data, not the data itself
Don't
- Create child loggers with dynamic namespaces without config
- Store context references outside their scope
- Log full request/response bodies
- Forget to flush before memory-intensive operations
- Skip transport cleanup on shutdown