Connect to ClickHouse
Connect ClickHouse to Retool to query analytics data and build apps and automations with SQL.
ClickHouse is an open-source column-oriented database management system designed for real-time analytics. After you create a ClickHouse resource in Retool, you can:
- Query analytical data using SQL with full support for ClickHouse-specific functions and aggregations.
- Run queries on billions of rows using ClickHouse's columnar storage and vectorized query execution.
- Build dashboards that connect to your ClickHouse cluster with live data.
- Insert records from Retool apps and automations.
Before you begin
To connect ClickHouse to Retool, you need the following:
- Cloud instances
- Self-hosted instances
- Database credentials: Username and password with appropriate read and write permissions.
- Network access: Database must accept connections from Retool's IP addresses. For databases not publicly accessible, configure an SSH tunnel.
- Retool permissions: Ability to create and manage resources in your organization.
- Database credentials: Username and password with appropriate read and write permissions.
- Network access: Database must be accessible from your Retool instance's network. For databases behind firewalls, configure an SSH tunnel.
- Retool permissions: Ability to create and manage resources in your organization.
Create a ClickHouse resource
Follow these steps to create a ClickHouse resource in Retool.
1. Create a new resource
In your Retool organization, navigate to Resources in the main navigation and click Create new → Resource. Search for ClickHouse and click the ClickHouse tile to begin configuration.

ClickHouse resource selection.
2. Configure general settings
Specify a name and description for the resource that indicates which database it connects to. The description provides more context to users and Assist about how to use the resource.
| Example name | Example description |
|---|---|
| Analytics database (readonly) | A read-only ClickHouse database with product analytics and event tracking data. |
| ClickHouse warehouse | Primary ClickHouse cluster with user behavior and metrics data. |
3. Configure resource credentials
Configure the connection settings for your ClickHouse resource.

ClickHouse connection settings.
Host
The hostname or IP address of your ClickHouse server.
abc123.us-east-1.aws.clickhouse.cloud
clickhouse.example.com
192.168.1.100
Port
The port number for your ClickHouse server. ClickHouse communicates over HTTP or HTTPS:
- Default HTTPS port:
8443(used when SSL is enabled — recommended) - Default HTTP port:
8123(used when SSL is disabled)
Database name
The name of the database to connect to on the ClickHouse server. Defaults to default if not specified.
SSH tunnel
If your ClickHouse server is not publicly accessible, configure an SSH tunnel to connect through a bastion host. Provide SSH host, port, username, and authentication method (password or private key).
4. Configure authentication
ClickHouse uses username and password authentication.

ClickHouse authentication settings.
Database username
The ClickHouse username to authenticate with. The default ClickHouse user is default.
Database password
The password for the specified user. Store this value in configuration variables or rather than hardcoding it.
5. Configure advanced options
Configure optional settings available under the Advanced options section of the resource configuration form.
Outbound region
- Cloud instances
- Self-hosted instances
If your organization uses outbound regions, select the region that should be used for requests to ClickHouse. This controls which geographic region your requests originate from, which is useful for reducing latency or meeting data residency requirements.
Self-hosted instances do not have the outbound region field. Connections originate from your Retool instance's network.
SSL/TLS
SSL is enabled by default and strongly recommended for production ClickHouse connections.
| Field | Description |
|---|---|
| SSL/TLS | Enable SSL/TLS encryption for the connection. Enabled by default. |
| CA certificate | Provide your certificate authority (CA) certificate for SSL verification. |
| Client key | For mutual TLS authentication, provide the client private key. |
| Client certificate | For mutual TLS authentication, provide the client certificate. |
| Verification mode | How the server certificate is verified: Full verification (validates certificate and hostname), Verify CA certificate (validates certificate only), or Skip CA certificate verification (disables verification). |
When SSL is enabled, Retool connects on port 8443 by default. When disabled, port 8123 is used.
ClickHouse Cloud requires SSL. Keep SSL enabled and use the default port 8443 when connecting to ClickHouse Cloud instances.
6. Test the connection
Click Test connection to verify Retool can connect to your ClickHouse database. If the test succeeds, you see a success message. If it fails, check the following:
- Network access: Ensure your ClickHouse server accepts connections from Retool's IP addresses or your self-hosted instance.
- Credentials: Verify username and password are correct.
- Port: Confirm the port matches your SSL setting (
8443for HTTPS,8123for HTTP). - SSL configuration: If using SSL, verify certificate settings match your server's requirements.
After testing the connection, click View in console to open the Debug Tools console. The console displays detailed information about the test, including the test query executed and its response, execution time, and error details if the test fails. This information is helpful for troubleshooting connection issues.
7. Save the resource
Click Create resource to save your ClickHouse resource. You can now use it in queries across your Retool apps and automations.
Query ClickHouse data
Once you've created a ClickHouse resource, you can query it in apps, workflows, and agent tools using SQL.
Create a query
You can create a ClickHouse query in a Retool app using Assist to generate queries with natural language, or manually using code.
- Assist
- Code
Use Assist to generate queries from natural language prompts. Assist can create queries to retrieve, filter, and aggregate data from your ClickHouse resource.
To create a query with Assist:
- In the Retool app IDE, click the Assist button at the bottom of the left toolbar to open the Assist panel (if not already visible).
- Write a prompt describing the data you want to retrieve, referencing your resource using
@. - Press Enter to submit the prompt.
- Select your ClickHouse resource when prompted.
- Review the generated query and click Run query to add it to your app.
To manually create a ClickHouse query in a Retool app:
- In the Retool app IDE, open the Code tab, then click + in the page or global scope.
- Select Resource query.
- Choose your ClickHouse resource.
- Write your SQL query.
Query configuration fields
Field values can be static (e.g., user_123) or dynamic by using an embedded expression (e.g., {{ userSelect1.value }}).
SQL mode
For reading data with custom SQL queries.
simple analytics query
The SQL statement to execute against your ClickHouse database. ClickHouse supports standard SQL along with ClickHouse-specific extensions for analytical workloads.
SELECT
toDate(event_time) AS date,
event_type,
count() AS total,
uniq(user_id) AS unique_users
FROM events
WHERE event_time >= now() - INTERVAL 30 DAY
GROUP BY date, event_type
ORDER BY date DESC, total DESC
LIMIT 1000
query with embedded expressions
Use embedded expressions to make queries dynamic based on component values.
SELECT
user_id,
event_type,
event_time
FROM events
WHERE event_type = {{ eventTypeSelect.value }}
AND toDate(event_time) >= {{ dateRange.value.start }}
AND toDate(event_time) < {{ dateRange.value.end }}
ORDER BY event_time DESC
LIMIT {{ table1.pagination.pageSize }}
OFFSET {{ table1.pagination.offset }}
Data types and formatting
ClickHouse has its own type system distinct from standard SQL databases. Understanding these types ensures correct data handling in your Retool apps.
Response data formats
ClickHouse queries return data in these formats:
| ClickHouse type | JavaScript type | Notes |
|---|---|---|
| Int8/16/32 | number | Signed integers. |
| Int64 | number | Signed 64-bit integer. Values outside ±2^53 may lose precision as a JavaScript number. |
| UInt8/16/32 | number | Unsigned integers. |
| UInt64 | number | Unsigned 64-bit integer. Values exceeding 2^53 may lose precision as a JavaScript number. |
| Float32/Float64 | number | Floating-point numbers. |
| Decimal | string | Returns as strings to preserve precision. Parse with parseFloat() if needed. |
| String/FixedString | string | Returns as JavaScript strings. |
| Date/Date32 | string | Returns ISO 8601 date string (e.g., 2025-01-21). |
| DateTime/DateTime64 | string | Returns ISO 8601 datetime string. |
| Array(T) | array | Returns as JavaScript arrays. |
| Nullable(T) | T | null | Returns null for missing values. |
ClickHouse query examples
The following examples demonstrate typical ClickHouse operations in Retool apps.
display aggregated metrics in a chart
First, create a query named metricsQuery to aggregate event data by time period.
SELECT
toStartOfDay(event_time) AS day,
count() AS events,
uniq(user_id) AS unique_users
FROM events
WHERE event_time >= now() - INTERVAL 30 DAY
GROUP BY day
ORDER BY day
Next, add a Chart component to the app and bind its data to {{ metricsQuery.data }}. Set the x-axis to day and add series for events and unique_users.
filter analytics data with user input
First, add input components for users to specify filters:
- A Select component (
eventTypeSelect) for filtering by event type. - A Date Range Picker component (
dateRange) for date filtering.
Next, write a query that references the input component values to filter data.
SELECT
user_id,
event_type,
event_time,
properties
FROM events
WHERE event_type = {{ eventTypeSelect.value }}
AND toDate(event_time) >= {{ dateRange.value.start }}
AND toDate(event_time) < {{ dateRange.value.end }}
ORDER BY event_time DESC
LIMIT 500
Queries that read data automatically run whenever any referenced input values change by default. As you update the input fields, the query retrieves new data based on the new values.
run a top-N analysis
Use SQL aggregation to find the most common values in a column.
SELECT
event_type,
count() AS occurrences,
round(count() * 100.0 / sum(count()) OVER (), 2) AS percentage
FROM events
WHERE toDate(event_time) = today()
GROUP BY event_type
ORDER BY occurrences DESC
LIMIT 10
Display the results in a Table component to show the top event types for the current day.
Best practices
Follow these best practices to optimize performance, maintain data integrity, and secure your database queries.
Performance
Use indexes
Add indexes on columns frequently used in WHERE clauses, JOIN conditions, and ORDER BY statements to speed up queries.
Example
CREATE INDEX idx_order_date ON orders (order_date);
CREATE INDEX idx_user_status ON users (status, created_at);
Limit result sets
Always use LIMIT to restrict the number of rows returned, especially for large tables displayed in tables or charts.
Example
SELECT id, name, email, created_at
FROM users
WHERE status = 'active'
ORDER BY created_at DESC
LIMIT 100
Use prepared statements
Retool automatically uses prepared statements for SQL database queries, which improves performance and prevents SQL injection. Use embedded expressions instead of string concatenation to take advantage of this.
Example
-- Use embedded expressions (Retool handles parameterization automatically)
SELECT * FROM orders WHERE user_id = {{ currentUser.id }}
-- Avoid string concatenation, which bypasses prepared statement benefits
SELECT * FROM orders WHERE user_id = '{{ currentUser.id }}'
Avoid SELECT *
Select only the columns you need rather than using SELECT * to reduce data transfer and improve performance.
Example
-- Specify only the columns your app needs
SELECT id, customer_name, amount, order_date
FROM orders
WHERE status = 'pending'
Use connection pooling
Retool automatically manages connection pooling for database resources. For high-traffic apps, consider increasing the pool size in the resource's advanced settings.
Security
Use configuration variables
Store values referenced in queries — such as schema names or environment-specific identifiers — in configuration variables or secrets rather than hardcoding them.
Example
SELECT * FROM {{ retoolContext.configVars.SCHEMA_NAME }}.orders
WHERE region = {{ retoolContext.configVars.DEFAULT_REGION }}
Apply least privilege
Grant database users only the minimum permissions needed. Use read-only credentials for resources used only for reading data.
Example
-- Create a read-only user for reporting queries
GRANT SELECT ON analytics.* TO retool_readonly;
-- Create a separate user with write access for specific tables only
GRANT SELECT, INSERT, UPDATE ON orders TO retool_writer;
Validate user input
Validate and sanitize user input before using it in queries, even when using embedded expressions or prepared statements.
Example
-- Validate that a numeric input is within an expected range before using it
SELECT * FROM orders
WHERE user_id = {{ numericInput1.value }}
LIMIT {{ Math.min(rowLimit.value, 1000) }}
Enable SSL/TLS
Use SSL/TLS encryption for connections to protect data in transit, especially when connecting over the internet. Enable this in the resource's advanced settings.
Use resource environments
Configure multiple resource environments to maintain separate database configurations for production, staging, and development.
Example
Use production, staging, and development environments with separate credentials for each. Apps automatically use the resource environment that matches the current deployment environment.
Data integrity
Use transactions
Wrap related operations in transactions to ensure atomicity. Rollback behavior depends on the database and statement type, so verify your resource's transaction semantics before relying on automatic rollback.
Example
BEGIN;
UPDATE accounts SET balance = balance - {{ amount.value }} WHERE id = {{ fromAccount.value }};
UPDATE accounts SET balance = balance + {{ amount.value }} WHERE id = {{ toAccount.value }};
COMMIT;
Validate before delete
Always show a confirmation dialog before executing DELETE operations to prevent accidental data loss.
Example
Use a Modal component with a confirmation message and wire the DELETE query to run only when the user confirms. Set the query to run manually so it does not execute on page load.
Handle errors gracefully
Configure error notifications and fallback behavior for failed queries to improve user experience.
Example
Use the query's onFailure event handler to show a Notification with a user-friendly error message. Reference {{ queryName.error }} to display the specific error details when needed.
Implement soft deletes
For sensitive data, consider marking records as deleted rather than physically removing them to preserve audit trails.
Example
-- Mark a record as deleted instead of removing it
UPDATE users
SET deleted_at = NOW(), deleted_by = {{ currentUser.email }}
WHERE id = {{ usersTable.selectedRow.data.id }}
Test with resource environments
Use separate development and staging databases to test queries before deploying to production. Configure different credentials per resource environment.
ClickHouse optimizations
Use time-based filters
Filter on timestamp columns whenever possible. ClickHouse's MergeTree engine sorts and partitions data by time, making time-based filters highly efficient even on large datasets.
example
-- Efficient: uses partition pruning on event_time
SELECT count() FROM events
WHERE event_time >= toStartOfMonth(now())
-- Inefficient: prevents partition pruning
SELECT count() FROM events
WHERE toMonth(event_time) = toMonth(now())
Use approximate functions
For large datasets where exact precision is not required, use approximate aggregate functions to reduce computation time.
example
SELECT
toDate(event_time) AS date,
uniqCombined(user_id) AS approx_unique_users,
quantileTDigest(0.95)(response_time_ms) AS p95_response_time
FROM events
GROUP BY date
ORDER BY date DESC
Prefer count() over count(*)
In ClickHouse, count() without arguments is optimized and does not require reading column data, making it slightly more efficient than count(*).
Related resources
Create a resource
Learn how to create and manage resources in Retool.
SQL queries
Write SQL queries to read data from your database.
SSH tunnels
Connect to databases that are not publicly accessible using an SSH tunnel.
SSL/TLS connections
Configure SSL/TLS certificates for secure database connections.
Resource environments
Configure separate credentials for production and non-production environments.
Configuration variables
Store sensitive values securely for use in queries and apps.