Skip to content

PostgreSQL

Connect Querri to your PostgreSQL database to run queries, analyze data, and create visualizations.

The PostgreSQL connector supports:

  • PostgreSQL 9.6+: All modern PostgreSQL versions
  • AWS RDS PostgreSQL: Managed PostgreSQL on AWS
  • Azure Database for PostgreSQL: Managed PostgreSQL on Azure
  • Google Cloud SQL for PostgreSQL: Managed PostgreSQL on GCP
  • Heroku Postgres: Heroku’s managed PostgreSQL
  • PostgreSQL database server
  • Database credentials with appropriate permissions
  • Network access to the database

Important: For cloud-hosted databases or databases behind firewalls, whitelist the following IP address:

18.189.33.77

This is Querri’s outbound IP address. Add this to your database firewall rules or security group.

  1. Navigate to Connectors

    • Go to Settings → Connectors
    • Click “Add Connector”
  2. Select PostgreSQL

    • Choose “PostgreSQL” from the database connectors
  3. Configure Connection

Host: your-database-host.com
Port: 5432 (default PostgreSQL port)
Database: your_database_name
Username: your_username
Password: your_password

Optional Settings:

  • SSL Mode:
    • require - Always use SSL (recommended)
    • prefer - Use SSL if available
    • disable - Don’t use SSL
  • Schema: Default is public
  • Connection Timeout: Default is 30 seconds
  1. Test Connection

    • Click “Test Connection” to verify
    • If successful, click “Save”
  2. Use in Projects

    • Create a new step → “Database Query”
    • Select your PostgreSQL connector
    • Write your SQL query

Add inbound rule:

Type: PostgreSQL
Protocol: TCP
Port: 5432
Source: 18.189.33.77/32
Description: Querri Access

Add firewall rule:

Rule Name: Querri
Start IP: 18.189.33.77
End IP: 18.189.33.77

Add authorized network:

Name: Querri
Network: 18.189.33.77/32

Heroku Postgres allows connections from any IP by default. No configuration needed.

Create a dedicated read-only user for Querri:

-- Create user
CREATE USER querri_readonly WITH PASSWORD 'secure_password_here';
-- Grant connect permission
GRANT CONNECT ON DATABASE your_database TO querri_readonly;
-- Grant schema usage
GRANT USAGE ON SCHEMA public TO querri_readonly;
-- Grant select on all tables
GRANT SELECT ON ALL TABLES IN SCHEMA public TO querri_readonly;
-- Grant select on future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO querri_readonly;

For data updates or inserts:

-- Create user
CREATE USER querri_readwrite WITH PASSWORD 'secure_password_here';
-- Grant connect permission
GRANT CONNECT ON DATABASE your_database TO querri_readwrite;
-- Grant schema usage
GRANT USAGE ON SCHEMA public TO querri_readwrite;
-- Grant table permissions
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO querri_readwrite;
-- Grant sequence permissions (for auto-increment columns)
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO querri_readwrite;
-- Grant future permissions
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO querri_readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO querri_readwrite;
SELECT
customer_id,
customer_name,
email,
created_at
FROM customers
WHERE status = 'active'
ORDER BY created_at DESC
LIMIT 100;
SELECT
DATE_TRUNC('month', order_date) as month,
COUNT(*) as order_count,
SUM(total_amount) as total_revenue,
AVG(total_amount) as avg_order_value
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY month DESC;
SELECT
c.customer_name,
c.email,
COUNT(o.order_id) as order_count,
SUM(o.total_amount) as lifetime_value
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE c.status = 'active'
GROUP BY c.customer_id, c.customer_name, c.email
HAVING COUNT(o.order_id) > 0
ORDER BY lifetime_value DESC
LIMIT 50;
SELECT
product_name,
category,
sales_amount,
RANK() OVER (PARTITION BY category ORDER BY sales_amount DESC) as rank_in_category,
SUM(sales_amount) OVER (PARTITION BY category) as category_total
FROM product_sales
WHERE sale_date >= '2024-01-01';

Ensure frequently queried columns have indexes:

CREATE INDEX idx_orders_customer ON orders(customer_id);
CREATE INDEX idx_orders_date ON orders(order_date);
CREATE INDEX idx_customers_email ON customers(email);

Always use LIMIT for large tables:

SELECT * FROM large_table
LIMIT 1000;

For repeated queries with different values, use parameters:

SELECT * FROM orders
WHERE customer_id = {{customer_id}}
AND order_date BETWEEN {{start_date}} AND {{end_date}};

Set parameters when executing the step.

Analyze query performance:

EXPLAIN ANALYZE
SELECT * FROM orders
WHERE customer_id = 123;
SELECT
customer_segment,
COUNT(*) as customer_count,
AVG(lifetime_value) as avg_ltv,
SUM(lifetime_value) as total_ltv
FROM customers
GROUP BY customer_segment
ORDER BY total_ltv DESC;
SELECT
DATE_TRUNC('day', order_date) as date,
COUNT(*) as orders,
SUM(total_amount) as revenue
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY DATE_TRUNC('day', order_date)
ORDER BY date;
SELECT
product_name,
current_stock,
reorder_level,
CASE
WHEN current_stock <= reorder_level THEN 'Reorder Needed'
WHEN current_stock <= reorder_level * 1.5 THEN 'Low Stock'
ELSE 'Adequate'
END as stock_status
FROM inventory
WHERE current_stock <= reorder_level * 2
ORDER BY current_stock ASC;

Problem: Cannot connect to database

Solutions:

  1. Verify IP 18.189.33.77 is whitelisted
  2. Check database host and port are correct
  3. Verify database is running and accessible
  4. Check SSL mode settings
  5. Verify network connectivity

Problem: Invalid credentials error

Solutions:

  1. Double-check username and password
  2. Verify user exists: SELECT * FROM pg_user WHERE usename = 'your_username';
  3. Check user has connect permission
  4. Verify database name is correct

Problem: Permission denied on table/schema

Solutions:

  1. Grant necessary permissions (see Database User Setup)
  2. Verify schema name is correct
  3. Check table ownership
  4. Run: \dp table_name to see table permissions

Problem: SSL connection failed

Solutions:

  1. Try different SSL modes (prefer, require, disable)
  2. Verify server SSL certificate is valid
  3. Check PostgreSQL SSL configuration
  4. For RDS, ensure SSL is enabled

Problem: Query takes too long to execute

Solutions:

  1. Add indexes to improve query performance
  2. Reduce result set size with LIMIT
  3. Optimize query with EXPLAIN ANALYZE
  4. Increase query timeout in connector settings
  5. Consider creating a materialized view

Create dedicated read-only user for analytics:

  • Prevents accidental data modification
  • Limits potential security impact
  • Easier to audit and monitor

Always use SSL for production databases:

SSL Mode: require

Grant only necessary permissions:

-- Only SELECT on specific tables
GRANT SELECT ON TABLE orders, customers TO querri_readonly;
-- Only specific columns
GRANT SELECT (customer_id, email, created_at) ON customers TO querri_readonly;
  • Minimum 16 characters
  • Mix of letters, numbers, symbols
  • Unique for each connector
  • Store securely

Monitor database access:

-- View active connections
SELECT * FROM pg_stat_activity
WHERE usename = 'querri_readonly';
-- View recent queries
SELECT * FROM pg_stat_statements
WHERE userid = (SELECT oid FROM pg_user WHERE usename = 'querri_readonly');

Querri uses connection pooling for efficiency:

  • Min connections: 1
  • Max connections: 10
  • Idle timeout: 5 minutes
  • Reuse: Connections are reused across queries

Tested and supported versions:

  • PostgreSQL 16.x ✓
  • PostgreSQL 15.x ✓
  • PostgreSQL 14.x ✓
  • PostgreSQL 13.x ✓
  • PostgreSQL 12.x ✓
  • PostgreSQL 11.x ✓ (limited support)
  • PostgreSQL 10.x ✓ (limited support)
  • PostgreSQL 9.6.x ✓ (limited support)
  • PostgreSQL Documentation: postgresql.org/docs
  • PostgreSQL Wiki: wiki.postgresql.org
  • Community Forum: postgresql.org/list