ORM detection
What qdeck reads from each ORM config, how environment variables are resolved, and what to do when detection misses.
For: developers.
qdeck ships with seven ORM detectors plus a .env fallback. This page documents what each one reads, how environment variable resolution works, and the limits of automatic detection.
Detection order
When you run qdeck in a project, detectors run in this order:
- Prisma
- Drizzle
- TypeORM
- Knex
- Sequelize
- Django
- Rails
.envfallback (only if none of the above match)
The first match wins. Run with --verbose to see which one matched and which files were inspected.
Prisma
| Property | Value |
|---|---|
| Config files | schema.prisma, prisma.config.ts, prisma.config.js |
| Search path | prisma/, project root |
What it reads
For classic schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}qdeck reads the provider and the url. If url is env("VAR"), the value is resolved from .env files.
For Prisma v6+ with prisma.config.ts or .js:
export default {
datasourceUrl: process.env.DATABASE_URL,
} satisfies PrismaConfigThe datasourceUrl field and process.env.X patterns are supported. Direct URL strings (url: "postgres://...") also work.
Drizzle
| Property | Value |
|---|---|
| Config files | drizzle.config.ts, drizzle.config.js, drizzle.config.mjs |
| Search path | Project root |
What it reads
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});Both the inline credentials form (host, port, user, password, database) and the url form are supported. dialect maps to the engine type.
TypeORM
| Property | Value |
|---|---|
| Config files | data-source.ts, data-source.js, ormconfig.json |
| Search path | Project root, src/ |
What it reads
For data-source.ts:
export const AppDataSource = new DataSource({
type: "postgres",
host: process.env.DB_HOST,
port: 5432,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: "myapp",
});The detector pulls type, host, port, username, password, database. process.env.X values are resolved from .env files.
For ormconfig.json, the same fields apply with JSON syntax.
Knex
| Property | Value |
|---|---|
| Config files | knexfile.js, knexfile.ts, knexfile.mjs |
| Search path | Project root |
What it reads
Knex configs are environment-keyed:
module.exports = {
development: {
client: "pg",
connection: process.env.DATABASE_URL,
},
production: {
client: "pg",
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: "myapp_prod",
},
},
};qdeck reads the environment based on NODE_ENV. If NODE_ENV is not set, it defaults to development. client maps to the engine type (pg, postgresql, mysql, mysql2, sqlite3).
Sequelize
| Property | Value |
|---|---|
| Config files | config/config.json, config/config.js, .sequelizerc |
| Search path | Project root, config/ |
What it reads
Like Knex, Sequelize configs are environment-keyed:
{
"development": {
"username": "root",
"password": null,
"database": "myapp_dev",
"host": "127.0.0.1",
"dialect": "postgres"
}
}dialect maps to the engine type. NODE_ENV selects the environment.
Django
| Property | Value |
|---|---|
| Config files | settings.py, settings/*.py modules |
| Search path | Project root, <project_name>/, config/, settings/ |
What it reads
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "myapp",
"USER": os.environ.get("DB_USER"),
"PASSWORD": os.environ.get("DB_PASSWORD"),
"HOST": "localhost",
"PORT": "5432",
}
}The default connection is used. ENGINE maps:
django.db.backends.postgresql→ PostgreSQLdjango.db.backends.mysql→ MySQLdjango.db.backends.sqlite3→ SQLite
os.environ.get("X"), os.getenv("X"), and env("X") patterns are resolved from .env files (if django-environ or similar is in use).
If you have multiple settings files (e.g., settings/development.py and settings/production.py), qdeck looks at the one matching DJANGO_SETTINGS_MODULE, falling back to settings.py.
Rails
| Property | Value |
|---|---|
| Config files | config/database.yml |
| Search path | Project root, config/ |
What it reads
default: &default
adapter: postgresql
encoding: unicode
pool: 5
development:
<<: *default
database: myapp_development
username: <%= ENV["DB_USER"] %>
password: <%= ENV["DB_PASS"] %>
host: localhostqdeck reads the environment matching RAILS_ENV (or RACK_ENV). If neither is set, it defaults to development. ERB tags <%= ENV["X"] %> are resolved from .env files (if dotenv-rails is in use).
YAML aliases (<<: *default) are expanded automatically.
.env fallback
If no ORM matches, qdeck scans these files in order:
.env.env.local.env.development.env.production
For each file, it looks for variables holding a database URL:
| Variable | Format |
|---|---|
DATABASE_URL | Most common |
DB_URL, POSTGRES_URL, POSTGRESQL_URL, MYSQL_URL, PG_URL, PG_CONNECTION_STRING | Common alternatives |
The first URL found is used. If you have multiple databases, the fallback picks the first one. Use a direct URL instead for explicit control:
qdeck postgres://user:pass@host/dbEnvironment variable resolution
qdeck reads .env files using a permissive parser:
- Quoted and unquoted values supported.
- Comments (
#) stripped. - Multi-line values not supported.
${VAR}interpolation supported..env.localoverrides.env..env.<NODE_ENV>overrides both, ifNODE_ENVmatches.
If a variable isn't found in any .env file, qdeck falls back to the actual process environment. If still not found, detection fails with an error pointing at the missing variable.
Environment classification
After detection, qdeck classifies the connection as local, staging, or production based on the host:
| Host pattern | Classified as |
|---|---|
localhost, 127.0.0.1, 0.0.0.0, *.local, host.docker.internal | local |
Hostnames containing staging, stage, dev, qa, test | staging |
| Everything else | production |
The classification is used to set the connection color in QueryDeck (green/orange/red). You can change it after the fact in the connection editor.
When detection misses
If detection finds the wrong database, or no database at all:
- Run
qdeck --verbose --dry-runto see what was inspected. - If the issue is in a specific file, fix the config or .env.
- Use a direct URL:
qdeck postgres://user:pass@host/db— no detection involved. - File a bug via the in-app feedback button. Include the redacted config we should detect.
What's next
- Commands and flags for the full reference
- Troubleshooting for install issues
- Drift Mode which uses the same parsers to compare your ORM schema to the real database