# How to Enable and Use Cypher Query Debugging in neomodel

> Learn how to enable and use Cypher query debugging in neomodel by setting environment variables or programmatically. Improve your Python Neo4j query development.

- Repository: [Neo4j Contrib/neomodel](https://github.com/neo4j-contrib/neomodel)
- Tags: how-to-guide
- Published: 2026-03-08

---

**Enable Cypher query debugging in neomodel by setting the `NEOMODEL_CYPHER_DEBUG` environment variable to `true` or programmatically setting `config.CYPHER_DEBUG = True`, then configure Python's logging system to output `DEBUG` level messages.**

The **neomodel** library (from the `neo4j-contrib/neomodel` repository) provides a built-in mechanism for logging every Cypher query sent to Neo4j, including execution parameters and timing data. This **Cypher query debugging** feature is essential for performance optimization and troubleshooting database interactions in both synchronous and asynchronous applications.

## Understanding the CYPHER_DEBUG Configuration Flag

The debugging capability is controlled through a centralized configuration system defined in [`neomodel/config.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/config.py). The flag is stored as a boolean field named `cypher_debug` within the `NeomodelConfig` dataclass, which automatically maps to the environment variable `NEOMODEL_CYPHER_DEBUG`.

```python

# neomodel/config.py (lines 137-142)

cypher_debug: bool = field(
    default=False,
    metadata={
        "env_var": "NEOMODEL_CYPHER_DEBUG",
        "description": "Enable Cypher debug logging",
    },
)

```

For backward compatibility, neomodel exposes this setting as a module-level property `CYPHER_DEBUG` on the `config` module. Accessing `config.CYPHER_DEBUG` invokes a getter that retrieves the value from the global configuration instance, while assigning to it updates the underlying `cypher_debug` field.

```python

# neomodel/config.py (lines 89-95)

@property
def CYPHER_DEBUG(self) -> bool:
    return _get_attr("cypher_debug")

```

## How Query Logging Works Under the Hood

When enabled, the database drivers in [`neomodel/sync_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/sync_/database.py) and [`neomodel/async_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/async_/database.py) intercept every Cypher execution to record timing and parameter data. After a query completes, the code calculates the elapsed time (`tte`) and checks two conditions before emitting a log entry:

1. The `NEOMODEL_CYPHER_DEBUG` environment variable (or `config.CYPHER_DEBUG`) evaluates to `True`.
2. The elapsed time exceeds the slow-query threshold defined by `NEOMODEL_SLOW_QUERIES` (defaulting to 0 seconds).

If both conditions are satisfied, the driver calls `logger.debug()` with a formatted string containing the raw Cypher query, the parameters dictionary, and the execution time.

```python

# neomodel/sync_/database.py (lines 38-48)

if os.environ.get("NEOMODEL_CYPHER_DEBUG", False) and tte > float(
    os.environ.get("NEOMODEL_SLOW_QUERIES", 0)
):
    logger.debug(
        "query: " + query + "\nparams: " + repr(params) + f"\ntook: {tte:.2g}s\n"
    )

```

The asynchronous implementation in [`neomodel/async_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/async_/database.py) (lines 46-56) contains identical logic, ensuring consistent debugging behavior across both sync and async database operations.

The logger instance is created at module import time using Python's standard `logging` module:

```python

# neomodel/sync_/database.py

logger = logging.getLogger(__name__)

```

This design allows you to control debug output destinations—whether stdout, stderr, or a file—by configuring Python's logging handlers and levels rather than modifying neomodel's internal behavior.

## Enabling Cypher Query Debugging

You can activate debugging through environment variables before application startup or programmatically at runtime. Both methods ultimately toggle the same underlying configuration flag.

### Method 1: Environment Variables

Set `NEOMODEL_CYPHER_DEBUG` to `true` before launching your Python process. To log every query regardless of execution time, set `NEOMODEL_SLOW_QUERIES` to `0`.

```bash
export NEOMODEL_CYPHER_DEBUG=true
export NEOMODEL_SLOW_QUERIES=0
python my_application.py

```

Setting `NEOMODEL_SLOW_QUERIES` to a positive number (e.g., `0.5`) filters the output to show only queries exceeding that duration in seconds, which is useful for identifying performance bottlenecks without cluttering logs with fast operations.

### Method 2: Runtime Configuration

Import the configuration module and toggle the flag programmatically. This approach is useful when you need to enable debugging conditionally based on application state.

```python
from neomodel import config
import logging

# Configure Python logging to capture DEBUG messages

logging.basicConfig(level=logging.DEBUG)

# Enable Cypher query debugging at runtime

config.CYPHER_DEBUG = True

# Optional: Set slow query threshold (seconds)

config.slow_queries = 0.0  # Log all queries

# config.slow_queries = 1.0  # Log only queries taking > 1 second

# Run your neomodel code as usual

# e.g., Person.create(name="Alice")

```

Note that `config.CYPHER_DEBUG` is a property that maps to the underlying `cypher_debug` field in the global configuration instance retrieved via `get_config()`.

### Configuring Python Logging

Since neomodel uses Python's standard `logging` module, you must configure a handler to see the debug output. Without this step, the debug messages are generated but suppressed by default logging settings.

```python
import logging

# Option 1: Basic configuration to stdout

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Option 2: Configure specifically for neomodel

logger = logging.getLogger("neomodel")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)

```

## Filtering Slow Queries with NEOMODEL_SLOW_QUERIES

The `NEOMODEL_SLOW_QUERIES` environment variable (and its programmatic equivalent `config.slow_queries`) acts as a duration threshold filter. When set to a value greater than zero, the debug logging logic in [`neomodel/sync_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/sync_/database.py) and [`neomodel/async_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/async_/database.py) compares the elapsed execution time (`tte`) against this threshold before emitting the log entry.

This mechanism allows you to isolate performance issues by logging only queries that exceed a specific execution time, reducing noise in high-throughput applications while capturing expensive operations for optimization analysis.

## Summary

- **Cypher query debugging** in neomodel is controlled by the `CYPHER_DEBUG` configuration flag, which maps to the `NEOMODEL_CYPHER_DEBUG` environment variable.
- The logging logic resides in [`neomodel/sync_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/sync_/database.py) and [`neomodel/async_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/async_/database.py), where the driver emits debug messages containing the raw Cypher string, parameters, and execution time.
- Use `NEOMODEL_SLOW_QUERIES` to filter output to queries exceeding a specific duration threshold.
- Configure Python's standard `logging` module to capture `DEBUG` level messages from the `neomodel` namespace to view the output.

## Frequently Asked Questions

### How do I disable Cypher query debugging after enabling it?

Set `config.CYPHER_DEBUG = False` in your code, or set the environment variable `NEOMODEL_CYPHER_DEBUG` to `false` before restarting your application. Since the configuration is checked at query execution time, changes take effect immediately for subsequent database operations.

### Does Cypher query debugging work with async neomodel operations?

Yes. The asynchronous driver in [`neomodel/async_/database.py`](https://github.com/neo4j-contrib/neomodel/blob/main/neomodel/async_/database.py) implements identical debug logging logic to the synchronous driver. When `CYPHER_DEBUG` is enabled, both sync and async queries emit debug messages through the standard Python logging system.

### Where does the debug output go by default?

By default, debug output is handled by Python's standard `logging` module using the logger named `neomodel.sync_.database` or `neomodel.async_.database`. If you have not configured logging, Python's default configuration typically suppresses DEBUG messages. You must explicitly configure `logging.basicConfig(level=logging.DEBUG)` or add a handler to see the output in stdout or a file.

### Can I filter to show only slow queries?

Yes. Set the `NEOMODEL_SLOW_QUERIES` environment variable (or `config.slow_queries` programmatically) to a positive number representing seconds. The debug logger will only emit messages for queries whose execution time exceeds this threshold, allowing you to focus on performance bottlenecks without logging fast, routine operations.