Drizzle Studio is a powerful database management interface that makes working with your database intuitive and efficient. Learn how to use it for development, debugging, and data management.
# Start Drizzle Studio
pnpm db:studio
# Output:
# Drizzle Studio is running on http://localhost:4983Navigate to http://localhost:4983 in your web browser.
Studio automatically connects using your DATABASE_URL from environment variables.
The interface shows all your tables, relationships, and data in a clean UI.
Main sections:
Drizzle Studio Interface:
📊 Tables (in sidebar)
├── 👥 users (45 rows)
├── 🏢 organizations (12 rows)
├── 👤 members (67 rows)
├── 📝 projects (23 rows)
├── ✅ tasks (156 rows)
└── 📧 notifications (234 rows)
Click any table to view its data in the main panel.
Column operations:
Row operations:
Double-click any cell to edit its value:
Before: John Doe
After: John Smith ✏️
Studio validates data types and constraints:
✅ Valid: "user@example.com" (email format)
❌ Invalid: "not-an-email" (constraint violation)
Changes are saved automatically or use Ctrl+S (Cmd+S on Mac).
1. Click the "Add Row" button (+)
2. Fill in the required fields
3. Studio auto-generates UUIDs for ID fields
4. Foreign key fields show dropdown with valid options
5. Save with Enter or click outside the row
Example - Creating a new user:
id: [auto-generated UUID]
name: "Jane Developer"
email: "jane@company.com"
role: "user" [dropdown: user, admin, moderator]
created_at: [auto-set to now()]
Select multiple rows:
Bulk actions:
Click relationship arrows to navigate:
users table
├── → members (user_id)
│ └── → organizations (organization_id)
│ └── → projects (organization_id)
│ └── → tasks (project_id)
├── → user_settings (user_id)
└── → notifications (user_id)
The relationship panel shows:
Interactive features:
-- Find all admin users
SELECT name, email, created_at
FROM users
WHERE role = 'admin'
ORDER BY created_at DESC;
-- Count users by role
SELECT role, COUNT(*) as count
FROM users
GROUP BY role;Syntax highlighting: Full SQL syntax highlighting and autocomplete Execution: Run queries with Ctrl+Enter (Cmd+Enter) Results: View results in formatted tables Export: Export query results to JSON, CSV, or SQL History: Access previous queries from history panel
View seed data results:
# Run seed command
pnpm db:seed
# Then open Studio to verify:
pnpm db:studioInspect seeded data:
Use Studio to understand your schema:
Use the Schema tab to see the complete database structure with relationships.
Click any table to see:
Interactive diagram showing how tables connect to each other.
Before code changes:
pnpm db:reset-seedCommon debugging scenarios:
-- Find tasks without projects
SELECT t.*
FROM tasks t
LEFT JOIN projects p ON t.project_id = p.id
WHERE p.id IS NULL;
-- Find members without users
SELECT m.*
FROM members m
LEFT JOIN users u ON m.user_id = u.id
WHERE u.id IS NULL;After running migrations or updates:
SELECT
'users' as table_name, COUNT(*) as count FROM users
UNION ALL
SELECT
'organizations', COUNT(*) FROM organizations
UNION ALL
SELECT
'projects', COUNT(*) FROM projects;-- Check for recent changes
SELECT table_name, COUNT(*) as count
FROM (
SELECT 'users' as table_name, created_at FROM users
WHERE created_at > NOW() - INTERVAL '1 hour'
UNION ALL
SELECT 'projects', created_at FROM projects
WHERE created_at > NOW() - INTERVAL '1 hour'
) recent_data
GROUP BY table_name;Use Studio's data grid to manually inspect a sample of records for correctness.
Export options:
# Export specific tables
# Select rows in Studio → Export button → Choose format
# Example exports:
users_export.json # User data with relationships
projects_export.csv # Project data for analysis
tasks_backup.sql # SQL INSERT statementsSave frequently used queries:
-- Template: Active users by role
SELECT role, COUNT(*) as count
FROM users
WHERE active = true
AND created_at > '{{start_date}}'
GROUP BY role
ORDER BY count DESC;
-- Template: Project completion report
SELECT
o.name as organization,
p.name as project,
COUNT(t.id) as total_tasks,
COUNT(CASE WHEN t.status = 'completed' THEN 1 END) as completed
FROM organizations o
JOIN projects p ON o.id = p.organization_id
LEFT JOIN tasks t ON p.id = t.project_id
WHERE p.created_at > '{{project_start_date}}'
GROUP BY o.id, o.name, p.id, p.name;Use Studio to identify slow queries:
-- Check table sizes
SELECT
schemaname,
tablename,
attname,
n_distinct,
correlation
FROM pg_stats
WHERE schemaname = 'public'
ORDER BY n_distinct DESC;
-- Analyze query performance
EXPLAIN ANALYZE
SELECT u.*, COUNT(p.id) as project_count
FROM users u
LEFT JOIN members m ON u.id = m.user_id
LEFT JOIN organizations o ON m.organization_id = o.id
LEFT JOIN projects p ON o.id = p.organization_id
GROUP BY u.id;Studio uses the same database configuration as your application:
# .env.local
DATABASE_URL="postgresql://user:pass@host:port/db"
# Optional: Custom Studio port
DRIZZLE_STUDIO_PORT=4983# Start on different port
pnpm db:studio --port 5000
# Start in verbose mode
pnpm db:studio --verbose
# Start with specific config
pnpm db:studio --config ./custom-drizzle.config.tsLaunch Studio at the beginning of development sessions to monitor database changes.
After making code changes, verify the results in Studio before committing.
Regularly reset your development database to ensure clean test conditions.
Production considerations:
Never use Studio with production databases. Studio allows direct data editing, which can be dangerous in production environments.
Safe practices:
For large databases:
Drizzle Studio is an essential tool for database development. Use it to understand your schema, verify data changes, debug issues, and prototype queries efficiently.