# How to Configure flush_on and flush_every in spdlog: Complete Control Over Log Buffering

> Master spdlog log buffering with flush_on and flush_every. Gain granular control over how and when your logs are written with this comprehensive guide.

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

---

**Use `spdlog::flush_on(level)` to set a global minimum log level that triggers immediate sink flushing, and `spdlog::flush_every(interval)` to start a background thread that periodically flushes all registered loggers at fixed intervals.**

The spdlog library provides two distinct mechanisms for controlling when buffered log data is physically written to output sinks. These settings, implemented in the `gabime/spdlog` repository, allow developers to balance performance (buffering) against durability (immediate disk writes) based on application requirements.

## Understanding Flush Mechanisms in spdlog

spdlog manages sink flushing through a central registry pattern. The two primary configuration options operate at different granularities and serve different use cases.

### Global Flush Level (flush_on)

The **global flush level** determines the minimum log severity that automatically triggers a flush after each applicable log record. When configured, any message with a level greater than or equal to the threshold causes an immediate flush of that logger's sinks.

According to the source code in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h) (lines 81-82), the function `spdlog::flush_on()` forwards to `details::registry::instance().flush_on(log_level)`, with the implementation residing in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h) (lines 65-66). The registry stores this threshold in the `flush_level_` member variable (defaulting to `level::off`).

### Periodic Background Flushing (flush_every)

The **periodic flushing** mechanism creates a background thread that calls `flush_all()` on the registry at specified intervals. This ensures that buffered log entries are written to disk even if no high-severity messages trigger an automatic flush.

As implemented in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h) (lines 84-87), `spdlog::flush_every()` delegates to `details::registry::instance().flush_every(interval)`, which instantiates a `periodic_worker` object stored in `registry::periodic_flusher_`. This worker executes the lambda `[this]() { this->flush_all(); }` repeatedly using the specified duration.

## Configuring flush_on for Immediate Critical Logging

Set a global flush level to ensure critical messages are immediately persisted without waiting for buffer fills or periodic cycles.

### Global Configuration

Apply `flush_on` to the global registry to affect all loggers:

```cpp
#include <spdlog/spdlog.h>
#include <spdlog/level.h>

int main() {
    // Flush automatically on warnings or higher
    spdlog::flush_on(spdlog::level::warn);
    
    spdlog::info("This remains buffered");
    spdlog::warn("This triggers immediate flush");
    spdlog::error("This also triggers immediate flush");
}

```

The call routes to `registry::flush_on()`, which updates the `flush_level_` atomic used by all loggers in the global registry.

### Per-Logger Configuration

Override the global setting for specific loggers using the logger's member method:

```cpp
auto file_logger = spdlog::basic_logger_mt("file_logger", "my.log");
file_logger->flush_on(spdlog::level::err);  // Only flush on error or critical

```

This per-logger configuration, defined in [`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h), allows fine-grained control where some loggers flush only on critical errors while others use the global threshold.

## Configuring flush_every for Background Periodic Flushing

Use `flush_every` when you need guaranteed durability within a specific time window, regardless of message severity.

```cpp
#include <spdlog/spdlog.h>
#include <chrono>

int main() {
    // Flush all registered loggers every 3 seconds
    spdlog::flush_every(std::chrono::seconds(3));
    
    spdlog::info("This message may be delayed by up to 3 seconds");
    // Background thread automatically flushes sinks
}

```

### Important Implementation Details

The `flush_every` mechanism creates a **periodic background thread** through the `periodic_worker` class defined in [`include/spdlog/details/periodic_worker.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/periodic_worker.h). This thread:

- Is created on the first call to `flush_every()` and joined when the registry is destroyed
- Can be reconfigured by subsequent calls, which replace the interval
- Iterates over all registered loggers via `registry::flush_all()`, invoking each sink's `flush()` method

Both mechanisms are **thread-safe**. The registry protects modifications using `std::mutex` (`flusher_mutex_` for the periodic worker and `logger_map_mutex_` for the logger registry) as implemented in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h).

## Combining flush_on and flush_every for Production Use

For robust logging in production applications, combine both strategies to ensure critical errors are written immediately while guaranteeing regular data persistence:

```cpp
spdlog::flush_on(spdlog::level::err);               // Immediate flush for errors
spdlog::flush_every(std::chrono::seconds(5));      // Periodic flush every 5 seconds

```

This configuration ensures that:

1. **Critical errors** trigger immediate disk writes via `flush_on`
2. **Standard informational logs** are guaranteed to be written within 5 seconds via `flush_every`
3. The **background thread** handles the periodic flushing without blocking application threads

## Summary

- **`spdlog::flush_on(level)`** sets a global threshold in `registry::flush_level_` that triggers immediate sink flushing when log messages meet or exceed the specified severity
- **`spdlog::flush_every(interval)`** starts a background `periodic_worker` thread that calls `flush_all()` on the registry at fixed intervals
- Per-logger flush levels can be set via `logger::flush_on()` to override global settings
- Both mechanisms are thread-safe, using mutex protection in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h)
- Use `flush_on` for critical error persistence and `flush_every` for guaranteed durability of standard logs

## Frequently Asked Questions

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

`flush_on` triggers flushing immediately after writing a log message that meets the level threshold, affecting only that specific log operation. `flush_every` creates a background thread that flushes all sinks periodically regardless of content, ensuring data is written within a specific time window even if no high-level logs occur.

### Can I set different flush levels for different loggers?

Yes. While `spdlog::flush_on()` sets the global default in the registry, individual loggers expose a `flush_on()` member method. As implemented in [`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h), this allows you to configure sensitive loggers to flush on warnings while keeping verbose debug loggers buffered until periodic flushes occur.

### Is flush_every safe to use with single-threaded loggers?

You should only use `flush_every` when all registered loggers are thread-safe (e.g., created with `*_mt` variants). The background thread calls `flush_all()`, which iterates through all loggers and may invoke sink operations concurrently with application threads. For single-threaded (`*_st`) loggers, use explicit `logger->flush()` calls instead.

### How do I stop the periodic flusher?

The periodic flusher thread runs until the registry is destroyed. Call `spdlog::shutdown()` or allow the registry singleton to be destroyed at program exit. This joins the `periodic_worker` thread cleanly. You cannot stop the flusher independently while keeping the registry active, though calling `flush_every` with a new interval replaces the existing periodic worker.