Flush policies
A log line that's still sitting in a buffer when the process dies never existed, as far as anyone debugging the crash is concerned. Flushing is the knob between durability (get it to disk now) and throughput (batch writes, flush less often) — spdlog gives you several ways to set it.
Manual flush
logger->flush(); // one logger
spdlog::apply_all([](auto l) { l->flush(); }); // every registered logger
flush_on(level)
Flush automatically whenever a message at or above a given level is logged:
logger->flush_on(spdlog::level::err); // any err/critical message triggers an immediate flush
Messages below that level are still buffered normally — only reaching the threshold forces the flush.
Periodic flush
spdlog::flush_every(std::chrono::seconds(3));
This starts a background thread that flushes every registered logger on a timer, independent of message level.
The periodic-flush background thread is itself a piece of global state with its own shutdown
requirements. Not calling spdlog::shutdown() before the process exits risks the thread still running
(or being torn down in an unspecified order relative to other statics) during global destruction. See
Logger lifecycle for the general shutdown-ordering
picture.
Comparison table
| Policy | Durability | Throughput cost | Use when |
|---|---|---|---|
| Never / manual only | Whatever's buffered at crash time is lost | None | Logs are purely diagnostic, loss is acceptable |
flush_on(err) | Errors and above always survive | Small — only on error-level messages | The default for most services |
flush_every(Ns) | Bounded loss window of N seconds | Small, amortized | Combine with flush_on(err) for belt-and-suspenders |
| Flush every message | Nothing is ever lost | High — one flush syscall per log call | Audit logs, compliance requirements |
Async and flush
A flush on an async logger has to drain whatever's still queued before it can actually flush the sink.
Calling logger->flush() on an async logger is a synchronous call from the caller's point of view —
it waits for the background worker to catch up. See
Thread pool and async logger for what's
actually happening on the other end of that wait.
Recommended default
Error-level messages hit disk immediately (you don't lose your last words on failure), and everything else gets flushed at least every few seconds without paying a flush cost on every single log call.
See also
- Global settings and best practices — flush policy as part of a full setup.
- File sinks — the durability trade-off this page addresses.
- Overflow policies — the other way async logging can lose messages.
- spdlog overview.