Add your first datasource.
Last updated
What you are building
A database AccessFlow can put queries in front of — connected, introspected, and then narrowed down so that even an approved query cannot reach more than it should. The connecting part takes a few minutes. The narrowing part is the work that matters, and it is the second half of this guide.
What do I need before adding a datasource?
A reachable host, and a database account for AccessFlow to use. Scope that account deliberately: AccessFlow governs who may ask for what, but the credentials you hand it still bound what is physically possible. A read-only account for a read-only datasource is the cheapest control you will ever apply.
1. Connect it
Sidebar → Datasources → add one. The wizard is four steps: Database type, Connection details, Connection test, Configuration.
The type picker is grouped into Bundled drivers, Connectors and Custom drivers, and each tile carries a badge telling you what will happen when you save:
- Bundled — ships inside the image. Only PostgreSQL.
- Downloaded — already fetched and cached on this deployment.
- Will download — fetched on first use, checksum-verified, then cached. Expect a slower first save, not a failure.
- Unavailable — the deployment is in offline driver mode or the cache is not writable.
Connection details adapts to the engine. Most ask for host, port, database name, username and password. Some do not:
| Engine | What it asks for instead |
|---|---|
| BigQuery | A GCP project and a service-account key in JSON. No host, port or username. |
| Databricks | Workspace host, a required warehouse HTTP path, and a personal access token. No username. |
| Snowflake | An account host and either a password or an unencrypted private key for key-pair auth. No port. |
| DynamoDB | An AWS region in place of the database name, plus an access key id and secret. |
| Elasticsearch / OpenSearch | Either a username and password, or an API key. |
| Cassandra / ScyllaDB | A local datacenter name, which is required. |
SSL mode is pre-filled from the engine's own default rather than one global default — PostgreSQL starts at full verification, while several others (ClickHouse and a number of the NoSQL engines) start disabled. Check it rather than assuming it.
Run the Connection test. It opens a real connection and runs a trivial probe — the plugin's own equivalent for non-JDBC engines. You can skip it, but a datasource that cannot connect is a datasource nobody can query.
Finally, Configuration: connection pool size, max rows per query, the review plan, whether reads and writes each require review, and the AI switches. Turning on AI analysis or text-to-SQL requires choosing an AI configuration in the same step — see turn on AI risk analysis.
Credentials are encrypted before storage and are never returned by any endpoint. If you keep secrets elsewhere, the password field also accepts a reference into HashiCorp Vault, AWS Secrets Manager or Azure Key Vault instead of a literal value.
2. Look at what you just connected
Open the datasource's settings. The Schema tab shows the introspected objects as a searchable tree; clicking a table previews sample rows — through the governed path, so masked columns show masked values, never the raw ones. The ER diagram tab renders the same schema as a graph, which is often the faster way to spot the tables you did not know were there.
This is worth doing before you write any policy. The next three sections all reference specific tables and columns, and the schema tab is where you find their real names.
3. Limit which tables can be queried
The table allow-list lives on the grant, not on the datasource. On the Permissions tab, a grant carries Allowed schemas and Allowed tables, both fed by the introspected schema.
AccessFlow enforces this by walking the parsed query and collecting every table it actually touches, then checking each one against the list. It is not a text match on the SQL, so aliases, comments and formatting cannot slip past it.
Two matching details worth knowing. Names are compared case-insensitively with quoting
stripped, so "Orders" and orders are the same entry. But
qualification is significant: an unqualified orders in the list matches an
unqualified FROM orders, so list the form your users actually write — or
allow the schema instead, which covers both.
4. Mask the columns that should not be read
The Masking tab defines column-level policies applied to results. Each
policy names a column as schema.table.column, picks a strategy, and lists who
may see through it.
- Full mask — the value is replaced entirely.
- Partial — keeps a number of trailing characters, for the last four digits of a card or an account.
- Hash — a SHA-256 digest, so values remain comparable without being readable.
- Email-preserving and format-preserving — keep the shape so downstream tools and eyeballs still recognise it.
Reveal to names the roles, groups or people who see the real value. Leave it empty and the column is masked for everyone, admins included — masking is opt-in for the reader, not opt-out.
5. Limit which rows come back
The Row security tab filters rows rather than columns. A policy names a table and a column, an operator, and a value to compare against — either a literal, or a variable resolved per user such as their region attribute, their role, or their groups.
AccessFlow applies it by rewriting the query: a SELECT gets its table wrapped in a filtered subquery, an UPDATE or DELETE gets the predicate added to its WHERE clause. The comparison value is always bound as a parameter, never concatenated into the SQL.
Non-relational engines each fail closed in their own way. Redis, for instance, cannot express row security at all, so a policy over it denies rather than degrades; Cassandra refuses policies on non-key columns instead of quietly scanning the whole table.
Unlike masking, row security applies to everyone by default: leaving Applies to empty means the policy is in force for all users. Narrow it to specific roles or groups if that is not what you want.
6. Keep an eye on it
Datasource health in the admin section shows connection-pool use, query volume, error counts and execution latency per datasource over the last day. It is the first place to look when queries start timing out — an exhausted pool looks very different from a slow database, and the page distinguishes them.
Field-by-field reference for every engine, the full policy options and the tuning env vars: Datasources. Engine-specific behaviour and install detail: Connectors.