# How to Check PostgreSQL WAL Status Using the mcp-postgresql-ops Tool

> Learn how to check PostgreSQL WAL status with mcp-postgresql-ops. Get current WAL position, archiving stats, and configuration with SQL queries for a clear report.

- Repository: [JungJungIn/mcp-postgresql-ops](https://github.com/call518/mcp-postgresql-ops)
- Tags: how-to-guide
- Published: 2026-02-26

---

**The `get_wal_status` tool aggregates current WAL position, archiving statistics, and configuration settings from PostgreSQL into a formatted report using three targeted SQL queries.**

The `call518/mcp-postgresql-ops` repository provides a Model Context Protocol (MCP) server for PostgreSQL operational tasks. Its **`get_wal_status`** tool offers comprehensive visibility into Write-Ahead Log activity, helping DBAs monitor replication health and disk usage without manual SQL execution.

## What WAL Information Does get_wal_status Provide?

The tool, implemented in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) (lines 37-71), issues three distinct queries against PostgreSQL. It combines the results into a single formatted string with clearly labeled sections.

### Current WAL Position and Generation

This query uses `pg_current_wal_lsn()` to determine the **Log Sequence Number (LSN)** and calculates megabytes generated since startup. It also determines whether the instance is a **primary** or **standby** using `pg_is_in_recovery()`.

Key columns include `current_wal_lsn`, `wal_mb_generated`, `server_role`, and `in_recovery`.

### Archiving Statistics

Data is retrieved from **`pg_stat_archiver`** to track WAL file archival success and failures. This reveals whether your archive command is keeping pace with WAL generation.

Key columns include `archived_count`, `last_archived_wal`, `last_archived_time`, `failed_count`, and `last_failed_time`.

### WAL Configuration Settings

The tool queries **`pg_settings`** for critical parameters that control WAL behavior. This includes `wal_level`, `archive_mode`, `archive_command`, `max_wal_size`, `min_wal_size`, `checkpoint_segments`, `checkpoint_completion_target`, and `wal_buffers`.

Each setting includes its current value and unit of measurement.

## Implementation Architecture

### Query Execution and Formatting

The `execute_query` function in [`src/mcp_postgresql_ops/functions.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/functions.py) establishes an asyncpg connection, executes the SQL, and converts results to dictionaries. The `format_table_data` helper then transforms raw bytes and duration columns into human-readable strings (e.g., converting bytes to megabytes).

### Version Compatibility

While `get_wal_status` uses stable PostgreSQL functions, the repository includes a **version-aware** layer in [`src/mcp_postgresql_ops/version_compat.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/version_compat.py). The `VersionAwareQueries.get_wal_receiver_query` method adapts to PostgreSQL 16+ columns (`written_lsn`, `flushed_lsn`) versus older versions. This is utilized by the separate **`get_replication_status`** tool, which complements `get_wal_status` by providing WAL receiver metrics on standby servers.

### Read-Only Design

The tool deliberately performs only read operations. The implementation explicitly excludes write or control actions such as `pg_switch_wal()`, which are documented as prohibited use cases in the function docstring.

## How to Query WAL Status

### Direct Python Async Call

```python
from mcp_postgresql_ops.mcp_main import get_wal_status

async def show_wal():
    info = await get_wal_status()
    print(info)

# In an async context:

# await show_wal()

```

### MCP Server HTTP Endpoint

```bash

# Assuming the MCP server is running and exposes the tool via HTTP:

curl -X POST http://localhost:8000/tools/get_wal_status

```

The response contains the formatted text with three labeled sections.

### Accessing Raw Data Programmatically

To bypass formatting and access raw rows, reuse the underlying queries through `execute_query`:

```python
from mcp_postgresql_ops.functions import execute_query

async def wal_raw():
    # Current WAL position

    wal_info = await execute_query("""
        SELECT pg_current_wal_lsn() AS current_wal_lsn,
               pg_wal_lsn_diff(pg_current_wal_lsn(), '0/0')/1024/1024 AS wal_mb_generated,
               CASE WHEN pg_is_in_recovery() THEN 'Recovery (Standby)' ELSE 'Primary' END AS server_role,
               pg_is_in_recovery() AS in_recovery
    """)

    # Archiver stats

    archiver = await execute_query("""
        SELECT archived_count, last_archived_wal, last_archived_time,
               failed_count, last_failed_wal, last_failed_time, stats_reset
        FROM pg_stat_archiver
    """)

    # WAL config

    config = await execute_query("""
        SELECT name, setting, unit
        FROM pg_settings
        WHERE name IN ('wal_level','archive_mode','archive_command',
                       'max_wal_size','min_wal_size','checkpoint_segments',
                       'checkpoint_completion_target','wal_buffers')
        ORDER BY name
    """)
    return wal_info, archiver, config

```

### Combining with Replication Status

For a complete WAL health check including standby receiver statistics:

```python
from mcp_postgresql_ops.mcp_main import get_wal_status, get_replication_status

async def wal_and_replication():
    print(await get_wal_status())
    print("\n---\n")
    print(await get_replication_status())   # includes WAL receiver info on a standby

```

## Summary

- The **`get_wal_status`** tool aggregates three data groups: current WAL position, archiving statistics, and configuration parameters.
- Implementation resides in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py) (lines 37-71), utilizing `execute_query` and `format_table_data` from [`src/mcp_postgresql_ops/functions.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/functions.py).
- The tool is **read-only** and does not perform write operations like `pg_switch_wal()`.
- For standby servers, pair this tool with **`get_replication_status`** to view WAL receiver progress via version-aware queries in [`src/mcp_postgresql_ops/version_compat.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/version_compat.py).
- Results are automatically formatted for human readability, converting byte counts and durations into readable units.

## Frequently Asked Questions

### What is the difference between get_wal_status and get_replication_status?

**`get_wal_status`** focuses on the local instance's WAL generation, archival success, and configuration. **`get_replication_status`** provides replication connection details and, crucially, WAL receiver statistics on standby servers (using `VersionAwareQueries.get_wal_receiver_query` to handle PostgreSQL version differences). Use both tools together for complete streaming replication monitoring.

### Can I use get_wal_status to force WAL rotation or archiving?

No. The tool is explicitly designed as **read-only**. According to the docstring in [`src/mcp_postgresql_ops/mcp_main.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/mcp_main.py), write or control actions such as executing `pg_switch_wal()` are prohibited use cases. You must connect to PostgreSQL directly with appropriate privileges to perform manual WAL switches.

### Does get_wal_status work with all PostgreSQL versions?

The tool relies on standard PostgreSQL functions like `pg_current_wal_lsn()` and `pg_stat_archiver` that are stable across recent versions. The repository specifically handles version differences for advanced features; for example, [`src/mcp_postgresql_ops/version_compat.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/version_compat.py) adapts WAL receiver queries for PostgreSQL 16+ column names (`written_lsn`, `flushed_lsn`) when used with `get_replication_status`.

### How does the tool format large byte values and timestamps?

The **`format_table_data`** function in [`src/mcp_postgresql_ops/functions.py`](https://github.com/call518/mcp-postgresql-ops/blob/main/src/mcp_postgresql_ops/functions.py) automatically detects columns ending in `_bytes` or `_size` and converts them to human-readable units (MB, GB). It similarly formats duration and timestamp columns for readability, ensuring the output requires no additional post-processing.