# How to Flush Log Messages Immediately in spdlog: 4 Methods Explained

> Learn to flush spdlog messages instantly. Discover 4 methods including manual flush logger flush, auto-flush by level, and force flush on sink construction.

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

---

**Call `logger->flush()` for manual flushing, use `spdlog::flush_on(level)` to auto-flush by severity, or construct sinks with `force_flush=true` to flush after every write.**

When building high-reliability applications with **gabime/spdlog**, you often need to ensure critical log entries persist to disk or console without delay. While the library buffers output for performance, you can override this behavior to **flush log messages immediately in spdlog** using several mechanisms built into the logger and sink architecture.

## Method 1: Explicit Manual Flushing with `flush()`

The most direct way to guarantee persistence is calling the **`flush()`** method on your logger instance. This invokes the internal **`flush_()`** routine, which iterates through all attached sinks and calls their respective `flush()` implementations.

```cpp
auto logger = spdlog::basic_logger_mt("file_logger", "logs.txt");
logger->info("Starting critical operation");
logger->error("Fatal condition detected");

// Force immediate write to underlying device
logger->flush();

```

This mechanism is declared in [`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h) and implemented in [`include/spdlog/logger-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger-inl.h), where `logger::flush()` delegates to the protected `flush_()` method that synchronizes each sink’s buffer.

## Method 2: Automatic Flushing by Severity Level

For hands-free operation, configure a **flush level** using **`spdlog::flush_on()`**. When a log message meets or exceeds this severity, the library automatically triggers a flush after writing the record.

```cpp
// Flush automatically for every message (trace is the lowest level)
spdlog::flush_on(spdlog::level::trace);

auto console = spdlog::stdout_color_mt("console");
console->info("This writes and flushes immediately");
console->debug("So does this");

```

The global registry stores this setting in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h), while each logger checks **`should_flush_()`** inside [`include/spdlog/logger-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger-inl.h) to determine whether to invoke `flush_()` after processing the log entry.

## Method 3: Construct Sinks with Force-Flush Enabled

Many sink constructors accept a **`force_flush`** boolean parameter. When set to `true`, the sink calls `flush()` after every log write, ensuring no buffering occurs at the sink level.

```cpp
// true enables force_flush
auto sink = std::make_shared<spdlog::sinks::stdout_sink_mt>(true);
auto logger = std::make_shared<spdlog::logger>("forced", sink);
spdlog::register_logger(logger);

logger->info("Instant persistence");

```

The `stdout_sink_base` class honors the `force_flush_` flag in [`include/spdlog/sinks/stdout_sinks-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/stdout_sinks-inl.h), calling `fflush(file_)` immediately after each write. File sinks implement similar logic in [`include/spdlog/sinks/basic_file_sink-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/basic_file_sink-inl.h), where they invoke **`file_helper_.flush()`** to synchronize with the filesystem.

## Method 4: Periodic Background Flushing (Alternative)

If strictly immediate flushing is not required but you want regular persistence without manual calls, use the background flusher. This spawns a thread that flushes all loggers at a set interval.

```cpp
// Flush all loggers every 500 milliseconds
spdlog::flush_every(std::chrono::milliseconds{500});

```

While this does not flush instantaneously with each log entry, it provides a middle ground between performance and durability. The periodic flusher is managed by the registry implementation in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h).

## Choosing the Right Immediate Flush Strategy

Select the appropriate mechanism based on your durability requirements:

- **Explicit `flush()`**: Use when you need point-in-time guarantees, such as before application exit or after critical error handling.
- **`flush_on(level)`**: Use when specific severity levels (e.g., `error` or `critical`) must always persist immediately, but lower levels can buffer.
- **Force-flush sinks**: Use when you control sink instantiation and require every single write to persist, common for console output or audit trails.
- **`flush_every()`**: Use when you can tolerate slight delay (milliseconds) and want to amortize flush costs across many loggers.

## Summary

- **Manual control**: Call `logger->flush()` to force all attached sinks to write their buffers immediately.
- **Severity-based**: Configure `spdlog::flush_on(level)` to auto-flush when messages meet a threshold, implemented via `should_flush_()` in the logger.
- **Sink-level**: Pass `true` to sink constructors (e.g., `stdout_sink_mt(true)`) to enable `force_flush_`, ensuring `fflush()` or equivalent after every write.
- **Architecture**: All flushing ultimately delegates to sink-specific implementations declared in [`include/spdlog/sinks/base_sink.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/base_sink.h) and specialized in files like [`include/spdlog/sinks/basic_file_sink-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/sinks/basic_file_sink-inl.h) which calls `file_helper_.flush()`.

## Frequently Asked Questions

### Does calling `flush()` block the calling thread?

Yes. When you invoke `logger->flush()`, the calling thread executes the flush sequence, which iterates through all sinks and invokes their blocking `flush()` operations. For file sinks, this typically triggers a system call like `fflush()` or `fsync()`, which waits until the OS confirms the write.

### What is the performance impact of flushing after every log message?

Significant. Each flush operation performs a system call and potentially disk I/O, which can reduce throughput by orders of magnitude compared to buffered logging. Use **force-flush sinks** or `flush_on(level::trace)` only when durability is more critical than performance, or during debugging sessions.

### Can I flush only specific sinks while keeping others buffered?

Yes. While `logger->flush()` flushes all attached sinks, you can access individual sinks via `logger->sinks()` and call `flush()` on specific ones. For example: `logger->sinks()[0]->flush();` This allows fine-grained control over which outputs require immediate persistence without affecting high-throughput file loggers.

### How do I ensure logs are flushed before my application exits?

Register an `atexit` handler or use a scope guard that calls `spdlog::shutdown()` or manually invokes `flush()` on your loggers. The global registry destructor attempts to flush all loggers, but explicit flushing ensures no messages are lost during abnormal termination.