---
url: /logly.zig/examples/write-modes.md
description: >-
  Example of controlling log file write modes in Logly.zig. Choose between
  append mode for persistent history or overwrite mode for fresh session logs.
---

# Sink Write Modes

Learn how to control whether log files are appended to or overwritten using the `writeMode` field.

## Overview

The `writeMode` field in `SinkConfig` controls how files are written:

* **Append Mode** (default, `writeMode = .append`): New logs are added to existing files, preserving history
* **Overwrite Mode** (`writeMode = .overwrite`): Files are truncated when the sink initializes, starting fresh
* **Append Rotate Mode** (`writeMode = .appendRotate`): Append with explicit rotation trigger

This is useful for scenarios like:

* **Append**: Permanent audit logs, error tracking, system history
* **Overwrite**: Session logs, temporary debug output, test runs
* **Append Rotate**: Logs that need explicit rotation control

## Append Mode (Default)

The default behavior appends logs to existing files:

```zig
const std = @import("std");
const logly = @import("logly");

pub fn main() !void {
    var gpa = std.heap.DebugAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Create logger with append mode sink
    const logger = try logly.Logger.init(allocator);
    defer logger.deinit();

    var config = logly.SinkConfig.file("logs/app.log");
    config.overwriteMode = false;  // Append mode (this is the default)
    
     _ = try logger.addSink(config);

    try logger.info("First run", @src());
    try logger.info("This is appended", @src());
}
```

Each time you run the application:

1. First run: Creates `logs/app.log` with 2 entries
2. Second run: Appends 2 more entries → file now has 4 entries
3. Third run: Appends 2 more entries → file now has 6 entries

**File grows continuously**, preserving all historical logs.

## Overwrite Mode

Start fresh each run by enabling overwrite mode:

```zig
const std = @import("std");
const logly = @import("logly");

pub fn main() !void {
    var gpa = std.heap.DebugAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Create logger with overwrite mode sink
    const logger = try logly.Logger.init(allocator);
    defer logger.deinit();

    var config = logly.SinkConfig.file("logs/session.log");
    config.overwriteMode = true;  // Enable overwrite mode
    
     _ = try logger.addSink(config);

    try logger.info("Fresh start", @src());
    try logger.info("Previous logs discarded", @src());
}
```

Each time you run the application:

1. First run: Creates `logs/session.log` with 2 entries
2. Second run: File is truncated, then has 2 entries (old ones gone)
3. Third run: File is truncated, then has 2 entries (old ones gone)

**File is reset each run**, showing only the current session.

## Mixed Modes

Combine both modes in a single logger:

```zig
const std = @import("std");
const logly = @import("logly");

pub fn main() !void {
    var gpa = std.heap.DebugAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const logger = try logly.Logger.init(allocator);
    defer logger.deinit();

    // Sink 1: Persistent audit log (append mode)
    var audit = logly.SinkConfig.file("logs/audit.log");
    audit.overwriteMode = false;  // Keep all history
     _ = try logger.addSink(audit);

    // Sink 2: Current session debug log (overwrite mode)
    var debug = logly.SinkConfig.file("logs/debug.log");
    debug.overwriteMode = true;   // Fresh each run
     _ = try logger.addSink(debug);

    // Sink 3: Error log (append mode for permanent record)
    var errors = logly.SinkConfig.file("logs/errors.log");
    errors.level = .err;
    errors.overwriteMode = false;  // Keep error history
     _ = try logger.addSink(errors);

    try logger.info("Logged to audit.log and debug.log", @src());
    try logger.err("Logged to errors.log", @src());
}
```

**Result**:

* `audit.log`: Grows over time with all entries
* `debug.log`: Fresh each run, shows only current session
* `errors.log`: Grows over time with all error entries

## JSON Output

Overwrite mode works with JSON sinks too:

```zig
// JSON file that overwrites each run
var config = logly.SinkConfig.file("logs/session.json");
config.format = .json;
config.prettyJson = true;
config.overwriteMode = true;  // Overwrite JSON file
 _ = try logger.addSink(config);
```

## Use Cases

### Append Mode

* **Audit logs**: Keep permanent record of all events
* **Error tracking**: Maintain history of all errors
* **Production logs**: Accumulate data for analysis
* **Application history**: Track all user actions

```zig
// Permanent error log
var errors = logly.SinkConfig.file("logs/errors.log");
errors.level = .err;
errors.overwriteMode = false;  // Never discard
 _ = try logger.addSink(errors);
```

### Overwrite Mode

* **Debug sessions**: Fresh logs for each debugging session
* **Test runs**: Clean output for each test
* **Development**: Don't accumulate noise during development
* **Temporary logs**: Logs meant for current session only

```zig
// Fresh debug log each time
var debug = logly.SinkConfig.file("logs/debug.log");
debug.overwriteMode = true;  // Reset each run
 _ = try logger.addSink(debug);
```

## Performance Considerations

* **Append mode**: Slightly faster (no truncation overhead)
* **Overwrite mode**: Minimal overhead from file truncation at initialization

Both modes use the same high-performance async writing internally.

## File Rotation

The `overwriteMode` parameter works independently from file rotation:

```zig
// Rotation + Append mode: rotated files accumulate
var config = logly.SinkConfig.file("logs/app.log");
config.rotation = "daily";      // Daily rotation
config.overwriteMode = false;  // Append mode
config.retention = 7;           // Keep 7 days of rotated files
 _ = try logger.addSink(config);
```

## See Also

* [File Rotation](rotation.md)
* [Async Writing](async-logging.md)
* [File Logging](file-logging.md)
* [Sink Configuration](../api/sink.md)
