# Configuring Periodic Flush with spdlog flush_every(): A Complete Guide

> Learn to configure spdlog flush_every() for automatic log flushing. Ensure logs reach disk with this complete guide to periodic flushes.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: how-to-guide
- Published: 2026-07-12

---

**Use `spdlog::flush_every(std::chrono::duration)` to enable a background thread that automatically flushes all registered loggers at regular intervals, ensuring buffered logs are written to disk without manual intervention.**

The **gabime/spdlog** library provides a robust mechanism for periodic log flushing through the `flush_every()` function. This feature is essential when working with buffered sinks—such as file or rotating file sinks—where you want to guarantee data persistence without calling `logger->flush()` after every log statement. Configuring periodic flush with spdlog `flush_every()` offloads this responsibility to a dedicated background thread managed by the library's internal registry.

## How spdlog::flush_every() Works

The periodic flush mechanism operates through a cooperation between the public API and the internal registry singleton.

### The Public API Interface

The entry point for this feature is the inline helper function defined in [[`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h)](https://github.com/gabime/spdlog/blob/v1.x/include/spdlog/spdlog.h):

```cpp
template<typename Rep, typename Period>
inline void flush_every(std::chrono::duration<Rep, Period> interval) {
    details::registry::instance().flush_every(interval);
}

```

This template accepts any `std::chrono::duration` type, allowing you to specify intervals using `std::chrono::seconds`, `std::chrono::minutes`, or other duration units.

### Registry Singleton and Thread Management

When you invoke `flush_every()`, the call forwards to **`details::registry::instance()`**, which lives in [[`src/spdlog.cpp`](https://github.com/gabime/spdlog/blob/main/src/spdlog.cpp)](https://github.com/gabime/spdlog/blob/v1.x/src/spdlog.cpp). The registry maintains a background thread that:

1. Waits for the specified interval using a condition variable
2. Iterates over all registered loggers via `spdlog::apply_all([](auto& l){ l->flush(); })`
3. Calls each logger's `flush()` method, which propagates to individual sink implementations

If the interval is non-zero, the registry starts (or restarts) this thread. Passing a zero-duration (`std::chrono::seconds(0)`) stops the thread entirely, disabling automatic flushing.

## Implementation Details in the Source Code

The periodic flush implementation spans several key files in the repository:

- **[`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h)**: Declares the public `flush_every()` template function
- **[`src/spdlog.cpp`](https://github.com/gabime/spdlog/blob/main/src/spdlog.cpp)**: Contains the `registry` class implementation that manages the background flusher thread lifecycle (creation, joining on shutdown, and restart logic)
- **[`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h)**: Defines `logger::flush()`, which forwards the flush command to each sink's `flush_()` method
- **`include/spdlog/sinks/*_sink.h`**: Sink-specific implementations (e.g., `rotating_file_sink::flush_()` writes the file buffer to disk)

The thread ensures that all registered logger instances—whether synchronous or asynchronous—receive flush commands uniformly.

## Practical Code Examples

### Basic Periodic Flush Configuration

The following example demonstrates configuring a 2-second flush interval for a file logger:

```cpp
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <chrono>
#include <thread>

int main()
{
    // Create a logger that writes to a file
    auto file_logger = spdlog::basic_logger_mt("file_logger", "example.log");
    
    // Enable periodic flushing every 2 seconds
    spdlog::flush_every(std::chrono::seconds(2));
    
    // Log messages - they will be flushed automatically in the background
    for (int i = 0; i < 10; ++i) {
        file_logger->info("message {}", i);
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    }
    
    // Cleanup: Stop the periodic flusher before exit
    spdlog::flush_every(std::chrono::seconds(0));
}

```

### Test-Driven Usage Pattern

The spdlog test suite in [[`tests/test_misc.cpp`](https://github.com/gabime/spdlog/blob/main/tests/test_misc.cpp)](https://github.com/gabime/spdlog/blob/v1.x/tests/test_misc.cpp) provides a concrete validation example:

```cpp
auto logger = spdlog::create<test_sink_mt>("periodic_flush");
spdlog::flush_every(std::chrono::seconds(1));

// Allow time for the background thread to trigger
std::this_thread::sleep_for(std::chrono::milliseconds(1200));

// Verify flush occurred
REQUIRE(test_sink->flush_counter() == 1);

// Disable periodic flushing
spdlog::flush_every(std::chrono::seconds(0));

```

This pattern demonstrates that the background thread wakes up after the specified interval and invokes `flush()` on all loggers.

## Disabling the Periodic Flusher

To stop the background flush thread, call `flush_every()` with a zero duration:

```cpp
spdlog::flush_every(std::chrono::seconds(0));

```

According to the registry implementation in [`src/spdlog.cpp`](https://github.com/gabime/spdlog/blob/main/src/spdlog.cpp), this signals the background thread to exit its loop and join. After disabling, you must manually call `logger->flush()` if you require immediate buffer persistence.

## Summary

- **`spdlog::flush_every()`** creates a background thread that flushes all loggers at regular intervals defined by a `std::chrono::duration` parameter.
- The function is defined in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h) and delegates to `details::registry::instance().flush_every()` implemented in [`src/spdlog.cpp`](https://github.com/gabime/spdlog/blob/main/src/spdlog.cpp).
- Passing `std::chrono::seconds(0)` stops the periodic flusher thread.
- This mechanism works uniformly for both synchronous and asynchronous loggers (`spdlog::async_logger`) because the registry manages all logger types through the same `apply_all` interface.
- Periodic flushing prevents data loss in buffered sinks while avoiding the performance penalty of flushing on every log write.

## Frequently Asked Questions

### What is the difference between flush_every() and flush_on()?

**`flush_on()`** sets the log level that triggers an immediate flush after each log statement of that level or higher (e.g., `spdlog::flush_on(spdlog::level::warn)` flushes automatically when logging warnings or errors). In contrast, **`flush_every()`** operates on a time interval independent of log levels, flushing all buffered messages periodically regardless of their severity.

### Does flush_every() work with asynchronous loggers?

Yes. The periodic flush mechanism works with **asynchronous loggers** (`spdlog::async_logger`) because the registry's `apply_all()` method iterates over all registered loggers uniformly. When the background thread triggers, it calls `flush()` on each logger, which for async loggers ensures the underlying thread pool processes any remaining messages in the queue before the sinks flush.

### How do I stop the periodic flush thread?

Call `spdlog::flush_every(std::chrono::seconds(0))` or pass any zero-duration value. According to the implementation in [`src/spdlog.cpp`](https://github.com/gabime/spdlog/blob/main/src/spdlog.cpp), this stops the internal condition variable loop and joins the background thread. This is useful when you want to manually control flushing or during application shutdown to ensure proper cleanup.

### What happens to unflushed logs when the application crashes?

If the application crashes between automatic flush intervals, any log messages buffered in memory but not yet written to disk will be lost. To minimize this risk, configure a shorter flush interval for critical applications, or use `flush_on(spdlog::level::err)` to ensure immediate persistence of high-priority error messages while maintaining periodic flushing for lower-level debug logs.