[{"data":1,"prerenderedAt":414},["ShallowReactive",2],{"blog-guides/postgresql":3},{"id":4,"title":5,"body":6,"category":389,"date":390,"dateModified":390,"description":391,"draft":392,"extension":393,"faq":394,"featured":392,"headerVariant":398,"image":399,"keywords":399,"meta":400,"navigation":401,"ogDescription":402,"ogTitle":403,"path":404,"readTime":405,"schemaOrg":406,"schemaType":407,"seo":408,"sitemap":409,"stem":410,"tags":411,"twitterCard":412,"__hash__":413},"blog/blog/guides/postgresql.md","PostgreSQL Security Guide: Database Protection Basics",{"type":7,"value":8,"toc":361},"minimark",[9,16,21,24,29,45,49,52,66,76,80,84,98,102,105,128,137,141,144,148,162,166,177,181,185,188,202,206,209,226,230,234,248,252,266,270,284,288,302,330,349],[10,11,12],"tldr",{},[13,14,15],"p",{},"PostgreSQL is secure by default in many ways, but needs proper configuration. Enable SSL for all connections, use strong passwords, configure pg_hba.conf to limit access, create roles with minimal privileges, and always use parameterized queries. For multi-tenant apps, enable Row Level Security (RLS) to isolate user data.",[17,18,20],"h2",{"id":19},"connection-security","Connection Security",[13,22,23],{},"Secure how clients connect to your database:",[25,26,28],"h3",{"id":27},"enable-ssltls","Enable SSL/TLS",[30,31,32,36,39,42],"ul",{},[33,34,35],"li",{},"Require SSL for all connections in production",[33,37,38],{},"Use certificates from a trusted CA",[33,40,41],{},"Verify server certificates in your application",[33,43,44],{},"Consider client certificate authentication for sensitive systems",[25,46,48],{"id":47},"configure-pg_hbaconf","Configure pg_hba.conf",[13,50,51],{},"The pg_hba.conf file controls who can connect:",[30,53,54,57,60,63],{},[33,55,56],{},"Never allow passwordless local connections in production",[33,58,59],{},"Restrict IP ranges that can connect",[33,61,62],{},"Use scram-sha-256 for password authentication",[33,64,65],{},"Disable trust authentication",[67,68,69],"warning-box",{},[13,70,71,75],{},[72,73,74],"strong",{},"Important:"," Never expose PostgreSQL directly to the internet. Use a VPN, SSH tunnel, or place it behind a firewall with restricted access.",[17,77,79],{"id":78},"authentication-and-roles","Authentication and Roles",[25,81,83],{"id":82},"password-security","Password Security",[30,85,86,89,92,95],{},[33,87,88],{},"Use strong, unique passwords for each role",[33,90,91],{},"Store connection strings securely (environment variables)",[33,93,94],{},"Rotate passwords periodically",[33,96,97],{},"Consider using secrets managers",[25,99,101],{"id":100},"role-based-access-control","Role-Based Access Control",[13,103,104],{},"Create separate roles with minimal privileges:",[30,106,107,113,119,125],{},[33,108,109,112],{},[72,110,111],{},"Application role:"," Only SELECT, INSERT, UPDATE, DELETE on needed tables",[33,114,115,118],{},[72,116,117],{},"Read-only role:"," For analytics and reporting",[33,120,121,124],{},[72,122,123],{},"Admin role:"," For schema changes, used sparingly",[33,126,127],{},"Don't use the postgres superuser for applications",[129,130,131],"tip-box",{},[13,132,133,136],{},[72,134,135],{},"Principle of least privilege:"," Your application should have only the permissions it needs. If it never deletes data, don't grant DELETE. If it only reads certain tables, grant SELECT only on those.",[17,138,140],{"id":139},"row-level-security-rls","Row Level Security (RLS)",[13,142,143],{},"RLS is essential for multi-tenant applications:",[25,145,147],{"id":146},"what-rls-does","What RLS Does",[30,149,150,153,156,159],{},[33,151,152],{},"Automatically filters rows based on policies",[33,154,155],{},"Works at the database level, not application level",[33,157,158],{},"Protects against application bugs exposing data",[33,160,161],{},"Each query is filtered based on current user context",[25,163,165],{"id":164},"when-to-use-rls","When to Use RLS",[30,167,168,171,174],{},[33,169,170],{},"Multi-tenant SaaS applications",[33,172,173],{},"User-owned data (profiles, documents)",[33,175,176],{},"Any table where users should only see their own data",[17,178,180],{"id":179},"query-security","Query Security",[25,182,184],{"id":183},"preventing-sql-injection","Preventing SQL Injection",[13,186,187],{},"SQL injection is the most common database vulnerability:",[30,189,190,193,196,199],{},[33,191,192],{},"Always use parameterized queries",[33,194,195],{},"Never concatenate user input into SQL",[33,197,198],{},"Use an ORM that handles escaping",[33,200,201],{},"Validate and sanitize input as a defense in depth",[25,203,205],{"id":204},"using-prepared-statements","Using Prepared Statements",[13,207,208],{},"Prepared statements separate code from data:",[129,210,211],{},[13,212,213,216,217,221,222,225],{},[72,214,215],{},"Safe query pattern:"," Use ",[218,219,220],"code",{},"SELECT * FROM users WHERE id = $1"," with the parameter passed separately, not ",[218,223,224],{},"SELECT * FROM users WHERE id = '${userId}'",".",[17,227,229],{"id":228},"data-protection","Data Protection",[25,231,233],{"id":232},"encryption-at-rest","Encryption at Rest",[30,235,236,239,242,245],{},[33,237,238],{},"Enable disk encryption on database servers",[33,240,241],{},"Consider column-level encryption for sensitive data",[33,243,244],{},"Use pgcrypto for application-level encryption",[33,246,247],{},"Encrypt backups",[25,249,251],{"id":250},"sensitive-data-handling","Sensitive Data Handling",[30,253,254,257,260,263],{},[33,255,256],{},"Hash passwords with bcrypt or argon2",[33,258,259],{},"Consider encrypting PII columns",[33,261,262],{},"Implement data masking for non-production environments",[33,264,265],{},"Log access to sensitive data",[17,267,269],{"id":268},"monitoring-and-auditing","Monitoring and Auditing",[30,271,272,275,278,281],{},[33,273,274],{},"Enable query logging for security-sensitive operations",[33,276,277],{},"Monitor for unusual query patterns",[33,279,280],{},"Set up alerts for failed authentication attempts",[33,282,283],{},"Use pg_audit extension for detailed audit logs",[17,285,287],{"id":286},"updates-and-maintenance","Updates and Maintenance",[30,289,290,293,296,299],{},[33,291,292],{},"Keep PostgreSQL updated with security patches",[33,294,295],{},"Review and update roles periodically",[33,297,298],{},"Test backups regularly",[33,300,301],{},"Review pg_hba.conf when infrastructure changes",[303,304,305,312,318,324],"faq-section",{},[306,307,309],"faq-item",{"question":308},"What are the basic PostgreSQL security steps?",[13,310,311],{},"Enable SSL/TLS for connections, use strong passwords, configure pg_hba.conf to restrict access, create separate roles with minimal privileges, and keep PostgreSQL updated. Never run the database as root or expose it directly to the internet.",[306,313,315],{"question":314},"Should I use Row Level Security in PostgreSQL?",[13,316,317],{},"Yes, especially for multi-tenant applications. RLS lets you define policies that automatically filter data based on the current user, preventing users from accessing other users' data even if your application has bugs.",[306,319,321],{"question":320},"How do I prevent SQL injection in PostgreSQL?",[13,322,323],{},"Always use parameterized queries or prepared statements. Never concatenate user input into SQL strings. Use an ORM like Prisma or Drizzle that handles parameterization automatically.",[306,325,327],{"question":326},"Should I encrypt my PostgreSQL data?",[13,328,329],{},"At minimum, use SSL/TLS for connections and disk encryption on the server. For highly sensitive data, consider column-level encryption using pgcrypto. Always encrypt backups.",[331,332,333,339,344],"related-articles",{},[334,335],"related-card",{"description":336,"href":337,"title":338},"Postgres with RLS built-in","/blog/guides/supabase","Supabase Security Guide",[334,340],{"description":341,"href":342,"title":343},"Serverless Postgres","/blog/guides/neon","Neon Security Guide",[334,345],{"description":346,"href":347,"title":348},"Detailed protection guide","/blog/how-to/prevent-sql-injection","Prevent SQL Injection",[350,351,354,358],"cta-box",{"href":352,"label":353},"/","Start Free Scan",[17,355,357],{"id":356},"using-postgresql","Using PostgreSQL?",[13,359,360],{},"Scan your application for SQL injection and other database vulnerabilities.",{"title":362,"searchDepth":363,"depth":363,"links":364},"",2,[365,370,374,378,382,386,387,388],{"id":19,"depth":363,"text":20,"children":366},[367,369],{"id":27,"depth":368,"text":28},3,{"id":47,"depth":368,"text":48},{"id":78,"depth":363,"text":79,"children":371},[372,373],{"id":82,"depth":368,"text":83},{"id":100,"depth":368,"text":101},{"id":139,"depth":363,"text":140,"children":375},[376,377],{"id":146,"depth":368,"text":147},{"id":164,"depth":368,"text":165},{"id":179,"depth":363,"text":180,"children":379},[380,381],{"id":183,"depth":368,"text":184},{"id":204,"depth":368,"text":205},{"id":228,"depth":363,"text":229,"children":383},[384,385],{"id":232,"depth":368,"text":233},{"id":250,"depth":368,"text":251},{"id":268,"depth":363,"text":269},{"id":286,"depth":363,"text":287},{"id":356,"depth":363,"text":357},"guides","2026-01-27","Security guide for PostgreSQL users. Learn about authentication, role-based access, encryption, and secure configuration for your Postgres database.",false,"md",[395,396,397],{"question":308,"answer":311},{"question":314,"answer":317},{"question":320,"answer":323},"blue",null,{},true,"How to secure your PostgreSQL database with proper authentication, roles, and encryption.","PostgreSQL Security Guide","/blog/guides/postgresql","10 min read","[object Object]","BlogPosting",{"title":5,"description":391},{"loc":404},"blog/guides/postgresql",[],"summary_large_image","qzfpjsdX-s43sBmgsG5bqQrEipvLkbAlao4faL-MO4A",1775843929793]