# Database Query Plugin in Production: Best Practices for Dify Deployments

> Safely deploy the Dify database query plugin in production. Implement pre-authenticated variants, least-privilege users, and input validation for the junjiem/dify-plugin-tools-dbquery plugin.

- Repository: [Junjie.M/dify-plugin-tools-dbquery](https://github.com/junjiem/dify-plugin-tools-dbquery)
- Tags: best-practices
- Published: 2026-03-05

---

**Use the pre-authenticated variant with isolated credentials, enforce least-privilege database users, and validate all SQL inputs to safely run the junjiem/dify-plugin-tools-dbquery plugin in production environments.**

The **junjiem/dify-plugin-tools-dbquery** repository provides a powerful Dify plugin that enables LLM agents to execute SQL against MySQL, PostgreSQL, Oracle, and MSSQL databases. Deploying this **database query plugin in production** requires strict security controls, resource limits, and input validation to prevent credential exposure and SQL injection. The plugin architecture consists of a provider stub in [`db_query/provider/db_query.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/provider/db_query.py), tool definitions in [`db_query/tools/sql_query.yaml`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/tools/sql_query.yaml), and a daemon entry point at [`db_query/main.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/main.py).

## Security-First Configuration

### Isolate Credentials with Pre-Authentication

Never expose database credentials to the LLM or its logs. The repository provides a **pre-auth variant** (`db_query_pre_auth`) that separates credential handling from LLM prompts entirely.

Store all secrets in a `.env` file based on the template at `db_query/.env.example`, and ensure this file remains outside version control:

```bash

# db_query/.env

DB_TYPE=mysql
DB_HOST=db.internal.company.com
DB_PORT=3306
DB_USERNAME=readonly_analytics
DB_PASSWORD=super_secret_key
DB_NAME=production_db
MAX_REQUEST_TIMEOUT=120

```

Keep `.env` in `.gitignore` and mount it as a Docker secret or environment file rather than baking it into images.

### Enforce Least Privilege Database Access

Create a dedicated database user with **read-only permissions** (SELECT only) on specific tables. Avoid granting `DROP`, `INSERT`, `UPDATE`, or administrative rights unless the specific use case requires write operations. This limits the blast radius if the plugin is compromised or prompted maliciously.

### Network Isolation and Signature Verification

Run the plugin daemon inside a private Docker network with direct access only to the target database host. Do not expose the daemon ports publicly.

When installing from a private or local repository, add `FORCE_VERIFYING_SIGNATURE=false` to your Dify `.env` to bypass marketplace signature checks, as documented in the repository FAQ.

## Reliability and Performance Tuning

### Configure Request Timeouts

The plugin daemon defaults to `MAX_REQUEST_TIMEOUT=120` seconds as defined in [`db_query/main.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/main.py). Adjust this value based on your slowest acceptable query, but keep it as low as possible to prevent worker exhaustion from hanging connections.

```python

# In db_query/main.py or your wrapper

MAX_REQUEST_TIMEOUT = 120  # seconds

```

### Connection Management and Monitoring

Although the plugin uses simple SQLAlchemy-style connections, re-using the same daemon process reduces connection overhead. Deploy with Docker's `--restart=always` policy and allocate sufficient CPU/RAM.

Configure Dify's **Tool Usage** limits to prevent single users from flooding the database with requests. Forward daemon stdout/stderr to a log aggregation system (Loki, ELK, or CloudWatch), ensuring password masking is enabled to prevent credential leaks in logs.

## SQL Injection Prevention

### Validate and Sanitize Inputs

Even though the plugin executes raw SQL supplied by the LLM, you can mitigate injection risks through custom validation. Extend `DbQueryProvider._validate_credentials` in [`db_query/provider/db_query.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/provider/db_query.py) to implement a whitelist of allowed tables and columns, rejecting queries that reference unauthorized database objects.

If extending the plugin, use database drivers that support parameterized queries with placeholders (`%s` for MySQL, `:param` for PostgreSQL) rather than string interpolation:

```python

# Safe approach using parameters

cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

```

### Enforce Output Formats

Force the `output_format` parameter to `json` rather than Markdown. JSON is easier to sanitize programmatically and reduces the risk of prompt injection through malformed result formatting.

## Production Deployment Checklist

Before deploying the **database query plugin in production**, verify the following:

- **Environment File**: Populate `.env` with credentials and place it in `db_query/.env` (never commit to Git).
- **Provider Registration**: Confirm [`db_query/provider/db_query.yaml`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/provider/db_query.yaml) is present for Dify discovery.
- **Tool Schema**: Verify [`db_query/tools/sql_query.yaml`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/tools/sql_query.yaml) matches your supported `db_type` list.
- **Version Pinning**: Use a specific Git tag (e.g., `v0.0.11`) in your Dockerfile to prevent accidental upgrades.
- **Health Checks**: Implement a Docker `healthcheck` or custom `/health` endpoint to restart the daemon on failure.
- **Logging**: Centralize logs with password masking rules applied.

## Minimal Production Setup Example

### Environment Configuration

Copy the template and configure your production values:

```bash
cp db_query/.env.example db_query/.env

# Edit db_query/.env with production credentials

```

### Container Deployment

Create a Dockerfile that runs the daemon:

```dockerfile
FROM python:3.11-slim

WORKDIR /app
COPY db_query/ /app/
RUN pip install --no-cache-dir -r requirements.txt

# Load environment variables (do NOT commit this file)

COPY .env /app/.env
ENV PYTHONUNBUFFERED=1

CMD ["python", "-m", "db_query.main"]

```

Deploy via Docker Compose with network isolation:

```yaml
services:
  db_query_plugin:
    build: ./db_query
    env_file: ./db_query/.env
    restart: always
    networks:
      - dify_backend
      - database_network
    # Add Oracle 11g client volumes if needed

```

### Dify Integration

In the Dify plugin marketplace, reference the plugin directory or upload the offline package. The tool appears as **"Database Query"** with the `sql_query` operation. When invoked, Dify sends a request payload matching the schema defined in [`sql_query.yaml`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/sql_query.yaml):

```json
{
  "tool_name": "sql_query",
  "parameters": {
    "db_type": "mysql",
    "query_sql": "SELECT COUNT(*) FROM orders WHERE created_at > NOW() - INTERVAL 1 DAY",
    "output_format": "json"
  }
}

```

## Advanced Configuration

### Offline Package Deployment

For air-gapped environments, build the offline zip package described in the README's "How to install the offline version" section. This allows deployment without internet access to the Dify marketplace.

### Oracle 11g Client Setup

When connecting to Oracle 11g databases, follow the FAQ instructions to download the proprietary client libraries, mount them into the container, and adjust `LD_LIBRARY_PATH` accordingly.

### Custom Validation Policies

Implement organization-wide SQL policies by extending the `_validate_credentials` method in [`db_query/provider/db_query.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/provider/db_query.py). Add logic to deny specific keywords (e.g., `DROP`, `DELETE`) or restrict queries to specific schema patterns before execution.

## Summary

- **Use the pre-auth variant** (`db_query_pre_auth`) to keep credentials out of LLM context windows and logs.
- **Run database users with SELECT-only privileges** on specific tables to minimize security risks.
- **Set `MAX_REQUEST_TIMEOUT`** in [`db_query/main.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/main.py) to prevent worker hangs, and monitor daemon logs centrally.
- **Validate SQL inputs** through custom logic in `DbQueryProvider` and enforce JSON output formats for safer downstream processing.
- **Deploy via Docker** with `.env` files, restart policies, and private networks, pinning to specific Git tags for reproducibility.

## Frequently Asked Questions

### How do I prevent the LLM from seeing my database passwords?

Use the **pre-authenticated variant** located in the `db_query_pre_auth` directory. This version stores credentials in environment variables or configuration files that the LLM never accesses, unlike the standard variant where parameters might appear in prompts. Reference [`db_query_pre_auth/README.md`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query_pre_auth/README.md) for implementation details.

### What is the recommended timeout for production queries?

The default `MAX_REQUEST_TIMEOUT` is **120 seconds** as set in [`db_query/main.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/main.py). For production, set this to the 95th percentile of your query execution times plus a small buffer. Never set it to unlimited, as this can exhaust Dify's worker pool during database outages.

### Can I restrict which SQL commands the plugin executes?

Yes, though it requires customization. Extend the `_validate_credentials` method in [`db_query/provider/db_query.py`](https://github.com/junjiem/dify-plugin-tools-dbquery/blob/main/db_query/provider/db_query.py) to parse incoming SQL and reject queries containing forbidden keywords (like `DROP`, `DELETE`, or `UPDATE`) or tables outside an allowed whitelist. The repository provides a stub for this validation logic.

### How do I install this plugin without internet access?

Build the **offline package** following the repository README instructions. This creates a self-contained zip file that you can upload directly to Dify's plugin system without requiring external downloads, making it suitable for private data centers or secured environments.