How to Secure Database Connections
Database connections are high-value targets for attackers. An unsecured connection can expose credentials in transit, allow SQL injection, or provide unauthorized access to your entire dataset. This guide covers securing every aspect of database connectivity.
Find security issues automatically before attackers do.
Follow These Steps
Always use SSL/TLS for database connections
Encrypt data in transit between your application and database.
// PostgreSQL with SSL
import pg from 'pg'
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: true, // Verify server certificate
ca: process.env.DB_CA_CERT // CA certificate if self-signed
}
})
// MySQL with SSL
import mysql from 'mysql2/promise'
const connection = await mysql.createConnection({
uri: process.env.DATABASE_URL,
ssl: { rejectUnauthorized: true }
})Use least-privilege database users
Create separate database users for each service with only the permissions they need.
-- Create a restricted application user
CREATE USER app_readonly WITH PASSWORD 'strong-random-password';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_readonly;
CREATE USER app_readwrite WITH PASSWORD 'another-strong-password';
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO app_readwrite;
-- Never use the superuser for application connectionsStore credentials in environment variables
Never hardcode database credentials in source code.
# .env.local
DATABASE_URL=postgresql://app_readwrite:password@host:5432/mydb?sslmode=require
# On hosting platform, set via dashboard
# Vercel: Settings > Environment Variables
# Railway: ${{Postgres.DATABASE_URL}}Use parameterized queries exclusively
Never construct SQL with string concatenation.
// SAFE - parameterized
const result = await pool.query(
'SELECT * FROM users WHERE email = $1 AND status = $2',
[email, 'active']
)
// SAFE - ORM
const user = await db.select().from(users).where(eq(users.email, email))
// UNSAFE - string interpolation
const result = await pool.query(`SELECT * FROM users WHERE email = '${email}'`)Use connection pooling
Connection pools improve performance and limit the number of open connections.
const pool = new pg.Pool({
connectionString: process.env.DATABASE_URL,
max: 20, // Maximum connections in pool
idleTimeoutMillis: 30000, // Close idle connections after 30s
connectionTimeoutMillis: 5000 // Timeout if connection takes > 5s
})Enable query logging for audit
Log queries in development and suspicious patterns in production.
// Log slow queries in production
pool.on('connect', (client) => {
const originalQuery = client.query.bind(client)
client.query = (...args) => {
const start = Date.now()
const result = originalQuery(...args)
result.then(() => {
const duration = Date.now() - start
if (duration > 1000) {
console.warn(`Slow query (${duration}ms):`, args[0])
}
})
return result
}
})What You'll Achieve
Database connections use SSL/TLS encryption, least-privilege users, environment variable credentials, parameterized queries, connection pooling, and audit logging.
Common Mistakes to Avoid
Mistake
Using rejectUnauthorized: false in production
Fix
This disables SSL certificate verification. Use the CA certificate from your database provider and set rejectUnauthorized: true.
Mistake
Using the database superuser for the application
Fix
Create a restricted user with only SELECT, INSERT, UPDATE permissions. Never grant DROP, CREATE, or ALTER to the application user.
Frequently Asked Questions
Do managed databases like Supabase or PlanetScale handle security?
Managed databases handle server-side security (patching, encryption at rest) but you are still responsible for connection security (SSL, parameterized queries, access controls).
Is SSL required for database connections?
If your database is on a different server (which it almost always is in production), yes. Without SSL, credentials and data are sent in plaintext over the network.
Ready to Secure Your App?
VAS automatically scans your deployed app for the security issues covered in this guide. Get actionable results in minutes.
Start Security Scan