# Migrating from Log4j 2 to Logback in Spring Boot: Key Configuration Differences

> Effortlessly migrate logging from Log4j 2 to Logback in Spring Boot. Discover key configuration differences, file name changes, and placeholder syntax updates for smoother transitions.

- Repository: [Spring/spring-boot](https://github.com/spring-projects/spring-boot)
- Tags: migration-guide
- Published: 2026-02-16

---

**When migrating from Log4j 2 to Logback in Spring Boot, you must change configuration file names from [`log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2.xml) to [`logback.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback.xml), replace `${sys:...}` placeholders with Spring Boot's `${...}` syntax, and adapt to different default configuration structures while the framework automatically handles the Java Util Logging bridge.**

Spring Boot provides first-class support for both Log4j 2 and Logback in the `spring-projects/spring-boot` repository, but switching between these logging implementations requires understanding how each system discovers configuration files, resolves property placeholders, and integrates with Spring Boot's logging abstractions. This guide examines the core architectural differences to ensure a smooth **Log4j to Logback configuration** migration.

## Configuration File Discovery and Loading

The most immediate difference you'll encounter when migrating is how each logging system discovers its configuration files on the classpath.

### Log4j 2 Configuration Factory Approach

Log4j 2 relies on its `ConfigurationFactory` mechanism to locate configuration files. In [`Log4J2LoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/Log4J2LoggingSystem.java), Spring Boot bypasses the standard discovery process and explicitly calls `load()` with a specific location:

```java
// From Log4J2LoggingSystem.java
load(LogFile logFile, String location, List<Configuration> configurations)

```

This method processes files like [`log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2.xml) or [`log4j2-file.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2-file.xml) from the classpath. Spring Boot cannot use the classic "standard locations" approach with Log4j 2 because the `ConfigurationFactory` API doesn't expose the necessary hooks for Spring Boot's environment integration.

### Logback Standard Location Discovery

In contrast, [`LogbackLoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/LogbackLoggingSystem.java) implements a well-known location discovery mechanism that searches for:

- `logback-test.groovy`
- [`logback-test.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback-test.xml)
- `logback.groovy`
- [`logback.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback.xml)

If none of these files are found, Spring Boot falls back to its own default configuration ([`base.xml`](https://github.com/spring-projects/spring-boot/blob/main/base.xml)). This discovery happens in the `initialize()` method of `LogbackLoggingSystem`, which gives Spring Boot fine-grained control over the initialization process.

## Default Configuration Structure

When no custom configuration file is present, each system provides radically different default setups.

### Logback base.xml and defaults.xml

Logback's default configuration is defined in [`org/springframework/boot/logging/logback/base.xml`](https://github.com/spring-projects/spring-boot/blob/main/org/springframework/boot/logging/logback/base.xml). This file:

1. Imports [`defaults.xml`](https://github.com/spring-projects/spring-boot/blob/main/defaults.xml) which defines conversion rules like `clr` (color) and `wEx` (whitespace exception)
2. Sets up both console and file appenders
3. Defines color-aware patterns using Spring Boot's placeholder resolution

The [`defaults.xml`](https://github.com/spring-projects/spring-boot/blob/main/defaults.xml) file provides rich formatting options including the `%clr` converter for ANSI colors and `%wEx` for wrapped exceptions, which are automatically available in your [`logback.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback.xml) via the include mechanism.

### Log4j 2 Default Configuration

Log4j 2's default configuration lives in [`org/springframework/boot/logging/log4j2/log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/org/springframework/boot/logging/log4j2/log4j2.xml). This minimal configuration:

- Defines only a console appender (no file appender by default)
- Uses `${sys:...}` syntax for property resolution
- Includes a `<Select>` element that can switch between `StructuredLogLayout` and `PatternLayout` based on the `CONSOLE_LOG_STRUCTURED_FORMAT` system property

Unlike Logback's rich defaults, Log4j 2's default is intentionally minimal, requiring more explicit configuration for features like file logging or structured output.

## Property Placeholders and Syntax Differences

One of the most critical **Log4j to Logback configuration** migration concerns is the different placeholder syntax used by each system.

### Log4j 2 ${sys:...} Syntax

Log4j 2 uses the `${sys:PROPERTY_NAME}` syntax to reference system properties. In `Log4J2LoggingSystem`, Spring Boot injects its own properties (like `CONSOLE_LOG_PATTERN`) via `PropertiesUtil` before the configuration is parsed:

```java
// Properties are set via PropertiesUtil in Log4J2LoggingSystem
PropertiesUtil.getProperties().setStringProperty(key, value);

```

This means your [`log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2.xml) must use `${sys:LOG_DATEFORMAT_PATTERN}` or `${sys:CONSOLE_LOG_PATTERN}` to reference Spring Boot's logging properties.

### Logback ${...} Syntax

Logback uses Spring Boot's standard `${PROPERTY_NAME}` placeholder syntax, resolved by `LogbackLoggingSystem` through `LogbackLoggingSystemProperties`. The same property names (`LOG_DATEFORMAT_PATTERN`, `LOG_LEVEL_PATTERN`, etc.) are used, but the resolution mechanism is different:

```xml
<!-- In logback.xml -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN}}){faint} %clr(${LOG_LEVEL_PATTERN}) %clr(%pid){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD}}"/>

```

When migrating, you must replace all `${sys:...}` references with `${...}` and ensure you include the default Spring Boot includes ([`defaults.xml`](https://github.com/spring-projects/spring-boot/blob/main/defaults.xml)) to access the conversion rules.

## Java Util Logging Bridge Handling

Both systems handle the Java Util Logging (JUL) bridge automatically, but use different implementations.

### Logback SLF4JBridgeHandler

For Logback, `LogbackLoggingSystem.beforeInitialize()` installs the SLF4J bridge:

```java
// From LogbackLoggingSystem.java
loggerContext.getTurboFilterList().add(SUPPRESS_ALL_FILTER);
SLF4JBridgeHandler.install(); // installs JUL → SLF4J bridge

```

This routes all JUL calls through SLF4J to Logback, using a `TurboFilter` to suppress logging during the bootstrap phase.

### Log4j 2 Log4jBridgeHandler

For Log4j 2, `Log4J2LoggingSystem.configureJdkLoggingBridgeHandler()` installs the Log4j 2 bridge:

```java
// From Log4J2LoggingSystem.java
if (isJulUsingASingleConsoleHandlerAtMost() && !isLog4jLogManagerInstalled()
    && isLog4jBridgeHandlerAvailable()) {
    removeDefaultRootHandler();
    Log4jBridgeHandler.install(false, null, true); // installs JUL → Log4j2 bridge
}

```

The migration requires no code changes here—Spring Boot automatically swaps the appropriate bridge based on the active logging system detected on the classpath.

## Programmatic Log Level Changes

Both systems support runtime log level changes via `LoggingSystem.setLogLevel()`, but implement this differently in their respective `LoggingSystem` implementations.

### Logback Level Changes

`LogbackLoggingSystem.setLogLevel()` works with Logback `Level` objects and adds a `TurboFilter`-based suppressor while the system is being bootstrapped:

```java
// Conceptual implementation in LogbackLoggingSystem
void setLogLevel(String loggerName, LogLevel logLevel) {
    ch.qos.logback.classic.Logger logger = getLogger(loggerName);
    logger.setLevel(Level.toLevel(logLevel.name()));
}

```

### Log4j 2 Level Changes

`Log4J2LoggingSystem.setLogLevel()` works with Log4j 2 `Level` objects and creates a custom `LoggerConfig` when needed:

```java
// Conceptual implementation in Log4J2LoggingSystem
void setLogLevel(String loggerName, LogLevel logLevel) {
    LoggerConfig loggerConfig = getLoggerConfig(loggerName);
    if (loggerConfig == null) {
        loggerConfig = new LoggerConfig(loggerName, level, true);
        ctx.getConfiguration().addLogger(loggerName, loggerConfig);
    }
    loggerConfig.setLevel(convertToLog4jLevel(logLevel));
}

```

## Structured Logging Format Support

Both frameworks support structured logging (JSON output), but use different implementations and configuration approaches.

### Log4j 2 StructuredLogLayout

Log4j 2 provides its own `StructuredLogLayout` implementation in `org.springframework.boot.logging.log4j2.StructuredLogLayout`:

```java
// From StructuredLogLayout.java
@Plugin(name = "StructuredLogLayout", category = Node.CATEGORY)
public class StructuredLogLayout extends AbstractStringLayout {
    // Implements structured formatting for Log4j 2
}

```

This layout is referenced in the default [`log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2.xml) using the `<Select>` element to switch between structured and pattern layouts based on the `CONSOLE_LOG_STRUCTURED_FORMAT` property.

### Logback JsonWriterStructuredLogFormatter

Logback uses `JsonWriterStructuredLogFormatter` and a set of XML-based appenders:

```java
// From JsonWriterStructuredLogFormatter.java
public class JsonWriterStructuredLogFormatter<T> implements StructuredLogFormatter<T> {
    // Implements JSON formatting for Logback
}

```

Configuration uses includes like [`structured-console-appender.xml`](https://github.com/spring-projects/spring-boot/blob/main/structured-console-appender.xml) and [`structured-file-appender.xml`](https://github.com/spring-projects/spring-boot/blob/main/structured-file-appender.xml) rather than layout plugins.

## Summary

- **Configuration file discovery** differs significantly: Log4j 2 uses `ConfigurationFactory` with explicit loading via `Log4J2LoggingSystem.load()`, while Logback uses standard location discovery ([`logback.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback.xml), [`logback-test.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback-test.xml)) through `LogbackLoggingSystem`.
- **Placeholder syntax** must change from Log4j 2's `${sys:...}` to Logback's `${...}` when referencing Spring Boot properties like `CONSOLE_LOG_PATTERN` or `LOG_DATEFORMAT_PATTERN`.
- **Default configurations** vary in complexity: Logback provides rich defaults via [`base.xml`](https://github.com/spring-projects/spring-boot/blob/main/base.xml) and [`defaults.xml`](https://github.com/spring-projects/spring-boot/blob/main/defaults.xml) with color converters and file appenders, while Log4j 2 offers a minimal console-only default in [`log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2.xml).
- **JUL bridges** are handled automatically by Spring Boot, using `SLF4JBridgeHandler` for Logback and `Log4jBridgeHandler` for Log4j 2 without requiring manual code changes.
- **Structured logging** implementations differ: Log4j 2 uses `StructuredLogLayout` while Logback uses `JsonWriterStructuredLogFormatter` with XML-based structured appenders.

## Frequently Asked Questions

### What file name should I use when switching from Log4j 2 to Logback?

When migrating **Log4j to Logback configuration**, rename your configuration file from [`log4j2.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2.xml) (or [`log4j2-file.xml`](https://github.com/spring-projects/spring-boot/blob/main/log4j2-file.xml)) to [`logback.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback.xml) or [`logback-spring.xml`](https://github.com/spring-projects/spring-boot/blob/main/logback-spring.xml). Spring Boot's `LogbackLoggingSystem` automatically searches for these well-known locations in the classpath, whereas `Log4J2LoggingSystem` requires explicit file paths passed to its internal `load()` method.

### How do I convert Log4j 2 property placeholders to Logback syntax?

Replace Log4j 2's `${sys:PROPERTY_NAME}` syntax with Spring Boot's standard `${PROPERTY_NAME}` placeholders. In [`Log4J2LoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/Log4J2LoggingSystem.java), properties are injected via `PropertiesUtil` using the `${sys:...}` prefix, while [`LogbackLoggingSystem.java`](https://github.com/spring-projects/spring-boot/blob/main/LogbackLoggingSystem.java) resolves placeholders through `LogbackLoggingSystemProperties` using the standard `${...}` syntax. Ensure you include [`org/springframework/boot/logging/logback/defaults.xml`](https://github.com/spring-projects/spring-boot/blob/main/org/springframework/boot/logging/logback/defaults.xml) in your Logback configuration to access the standard conversion rules.

### Does Spring Boot automatically handle the Java Util Logging bridge when I switch logging systems?

Yes, Spring Boot automatically installs the appropriate JUL bridge based on the active logging system detected on the classpath. For Logback, `LogbackLoggingSystem.beforeInitialize()` installs `SLF4JBridgeHandler` alongside a `TurboFilter` to suppress bootstrap logging. For Log4j 2, `Log4J2LoggingSystem.configureJdkLoggingBridgeHandler()` installs `Log4jBridgeHandler` after verifying safe conditions. No manual intervention is required during your **Log4j to Logback configuration** migration.

### What are the key differences in structured logging support between Log4j 2 and Logback?

Log4j 2 implements structured logging through `StructuredLogLayout` in [`org/springframework/boot/logging/log4j2/StructuredLogLayout.java`](https://github.com/spring-projects/spring-boot/blob/main/org/springframework/boot/logging/log4j2/StructuredLogLayout.java), which is referenced in XML configuration using the `<Select>` element to toggle between structured and pattern layouts. Logback uses `JsonWriterStructuredLogFormatter` in [`org/springframework/boot/logging/structured/JsonWriterStructuredLogFormatter.java`](https://github.com/spring-projects/spring-boot/blob/main/org/springframework/boot/logging/structured/JsonWriterStructuredLogFormatter.java) along with XML-based includes like [`structured-console-appender.xml`](https://github.com/spring-projects/spring-boot/blob/main/structured-console-appender.xml) and [`structured-file-appender.xml`](https://github.com/spring-projects/spring-boot/blob/main/structured-file-appender.xml). When migrating structured logging configurations, you must switch from Log4j 2 layout plugins to Logback's formatter-based XML includes.