What Redis Operations Are Supported by DBX: Pattern Search and Key Scanning

DBX supports Redis key-pattern searching through a Rust-powered SCAN implementation that handles both single-node and cluster connections, offering batch aggregation via max_iterations to minimize network round-trips.

DBX is an open-source database management tool that provides comprehensive Redis operations, including advanced pattern-based key searching. The application implements a layered architecture using Tauri for the desktop frontend and Rust for the backend core, enabling efficient Redis SCAN operations with support for glob patterns like user:*. This architecture ensures both standalone and clustered Redis deployments can be queried with minimal latency through intelligent batching mechanisms.

Architecture Overview

DBX implements Redis operations through a three-tier architecture that separates UI concerns from database logic:

  1. Frontend (TypeScript) – UI components call Tauri commands via invoke
  2. Backend (Rust Tauri Commands) – Thin wrappers in src-tauri/src/commands/redis_cmd.rs validate and forward requests
  3. Core Library (crates/dbx-core) – Contains the actual Redis driver logic, handling connection pooling, database selection, and SCAN iteration

This design allows the same core logic to power both the desktop application and optional HTTP/web interfaces.

Frontend TypeScript API

The desktop UI interacts with Redis through typed functions in apps/desktop/src/lib/tauri.ts. These wrap the Tauri command layer and provide both single-scan and batch-scan variants:

// apps/desktop/src/lib/tauri.ts
export async function redisScanKeys(
  connectionId: string,
  db: number,
  cursor: number,
  pattern: string,
  count: number,
) {
  return invoke("redis_scan_keys", { connectionId, db, cursor, pattern, count });
}

export async function redisScanKeysBatch(
  connectionId: string,
  db: number,
  cursor: u64,
  pattern: string,
  count: number,
  maxIterations: number,
  includeTypes: boolean,
) {
  return invoke("redis_scan_keys_batch", {
    connectionId,
    db,
    cursor,
    pattern,
    count,
    maxIterations,
    includeTypes,
  });
}

The pattern parameter accepts Redis glob-style patterns (e.g., user:*, session:??), while count hints at how many keys Redis should return per iteration.

Backend Tauri Commands

The Tauri command handlers in src-tauri/src/commands/redis_cmd.rs act as bridges, forwarding parameters to the core library:

// src-tauri/src/commands/redis_cmd.rs
pub async fn redis_scan_keys(
    state: State<'_, Arc<AppState>>,
    connection_id: String,
    db: u32,
    cursor: u64,
    pattern: String,
    count: usize,
) -> Result<RedisScanResult, String> {
    dbx_core::redis_ops::redis_scan_keys_core(
        &state,
        &connection_id,
        db,
        cursor,
        &pattern,
        count,
    )
    .await
}

The batch variant passes additional parameters to enable server-side aggregation:

pub async fn redis_scan_keys_batch(
    state: State<'_, Arc<AppState>>,
    connection_id: String,
    db: u32,
    cursor: u64,
    pattern: String,
    count: usize,
    max_iterations: usize,
    include_types: bool,
) -> Result<RedisScanResult, String> {
    dbx_core::redis_ops::redis_scan_keys_batch_core(
        &state,
        &connection_id,
        db,
        cursor,
        &pattern,
        count,
        max_iterations,
        include_types,
    )
    .await
}

Both commands are registered in src-tauri/src/lib.rs to make them available to the frontend.

Core Redis Pattern Scanning Implementation

The actual Redis logic resides in crates/dbx-core/src/redis_ops.rs. The redis_scan_keys_core function delegates to a batch helper with a single iteration:

// crates/dbx-core/src/redis_ops.rs
pub async fn redis_scan_keys_core(
    state: &AppState,
    connection_id: &str,
    db: u32,
    cursor: u64,
    pattern: &str,
    count: usize,
) -> Result<RedisScanResult, String> {
    redis_scan_keys_batch_core(state, connection_id, db, cursor, pattern, count, 1, true).await
}

The redis_scan_keys_batch_core function handles connection multiplexing and executes up to max_iterations SCAN cycles server-side:

pub async fn redis_scan_keys_batch_core(
    state: &AppState,
    connection_id: &str,
    db: u32,
    cursor: u64,
    pattern: &str,
    count: usize,
    max_iterations: usize,
    include_types: bool,
) -> Result<RedisScanResult, String> {
    ensure_redis_pool(state, connection_id).await?;
    let connections = state.connections.read().await;
    let pool = connections.get(connection_id).ok_or("Connection not found")?;

    match pool {
        PoolKind::Redis(redis) => match redis {
            RedisConnection::Direct(con) => {
                let mut con = con.lock().await;
                redis_driver::select_db(&mut *con, db).await?;
                redis_driver::scan_keys_batch(
                    &mut *con,
                    cursor,
                    pattern,
                    count,
                    max_iterations,
                    include_types,
                )
                .await
            }
            RedisConnection::Cluster(cluster) => {
                redis_driver::ensure_cluster_db(db)?;
                // Cluster implementation handles distributed scanning
                // ...
            }
        },
        _ => Err("Not a Redis connection".to_string()),
    }
}

Key implementation details include:

  • Connection Type Handling – Distinguishes between RedisConnection::Direct for single-node setups and RedisConnection::Cluster for Redis Cluster deployments
  • Database Selection – Calls redis_driver::select_db for direct connections; validates DB index for clusters via ensure_cluster_db
  • Batch Aggregation – The max_iterations parameter controls how many SCAN cycles execute before returning to the frontend, drastically reducing round-trips when fetching large key sets
  • Type Metadata – When include_types is true, each RedisKeyInfo result includes the Redis type (string, hash, list, set, zset, etc.)
  • Result Structure – Returns a RedisScanResult containing the next cursor, a vector of RedisKeyInfo objects, and total matched key counts

Web API and HTTP Access

The same core scanning functions are exposed via HTTP in crates/dbx-web/src/routes/redis.rs. This allows external tools, browser extensions, or scripted clients to leverage DBX's Redis pattern searching without requiring the Tauri desktop runtime, using identical redis_scan_keys_core logic.

Real-Time Operations with Pub/Sub

Beyond pattern scanning, DBX supports real-time Redis operations through src-tauri/src/commands/redis_pubsub_server.rs. This module enables subscription-based notifications for key changes, complementing the scan functionality for use cases requiring live updates rather than point-in-time queries.

Summary

  • Pattern Search – DBX implements redis_scan_keys_core in crates/dbx-core/src/redis_ops.rs supporting glob patterns like user:* via Redis SCAN
  • Batch Mode – The max_iterations parameter aggregates multiple SCAN cycles server-side, minimizing frontend-backend round-trips
  • Cluster Support – Core logic handles both RedisConnection::Direct and RedisConnection::Cluster with appropriate database selection strategies
  • Type Metadata – Optional include_types flag returns key types (string, hash, list, etc.) alongside key names
  • Multi-Interface – Available via TypeScript/Tauri in apps/desktop/src/lib/tauri.ts and HTTP routes in crates/dbx-web/src/routes/redis.rs
  • Complementary Operations – Pub/Sub support via redis_pubsub_server.rs enables real-time key monitoring

Frequently Asked Questions

Does DBX support Redis Cluster for pattern searching?

Yes, according to the crates/dbx-core/src/redis_ops.rs source code, DBX handles both RedisConnection::Direct for standalone instances and RedisConnection::Cluster for clustered deployments. The implementation validates database selection for clusters and manages distributed SCAN operations across cluster nodes.

How does DBX optimize scanning large key spaces?

DBX uses a batching mechanism controlled by the max_iterations parameter in redis_scan_keys_batch_core. Instead of requiring a network round-trip for every SCAN cursor increment, the backend executes multiple scan cycles (up to max_iterations) before returning aggregated results to the frontend, significantly reducing latency when iterating large datasets.

Can I retrieve key data types while performing pattern searches?

Yes, by setting the include_types parameter to true in redisScanKeysBatch, the returned RedisKeyInfo objects contain the Redis type for each matched key (such as string, hash, list, set, or zset). This allows the UI to display appropriate icons or handling logic without requiring additional TYPE commands.

Is Redis pattern search available outside the desktop application?

Yes, the same core functions exposed to the Tauri frontend are also available via HTTP endpoints in crates/dbx-web/src/routes/redis.rs. This enables web-based clients, CLI tools, or automation scripts to use DBX's optimized Redis scanning capabilities without running the desktop application.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →