The database console
A database you run on Flui has no address on the internet. That is the right default, but the first time a row looks wrong you need a way to look inside it. The usual options all cost something. Opening the database to the internet undoes the default. Hosting a second web tool in front of it means you run, patch and secure that tool as well. A native client means setting up a tunnel every time.
The console is a data browser built into the dashboard and served through Flui’s own backend. Nothing is exposed, and there is nothing extra to install.
This chapter covers what it opens, who may open it, how it connects, and the limits it sets.
The kinds of console
There are about ten kinds of console. The list follows the building blocks Flui’s catalog installs, and each console has the same shape: a panel of connection details, a way to browse what is stored, and a way to run something by hand.
- Relational: Postgres and MariaDB. A query editor, a schema browser that reads tables, columns, primary keys and foreign keys, and the connection details.
- Key-value: Redis and Valkey. A keyspace summary (counts, not contents), a key scan, a value reader and a command runner.
- Cache: Memcached. Read a key, set one, delete one, flush.
- Document: FerretDB, driven with the shell statements a MongoDB user already knows, plus a browser for databases, collections and fields.
- Full-text: Meilisearch. The indexes, a search box, and a raw call for anything the box does not cover.
- Kafka: the cluster, its topics and its consumer groups, plus a command shell.
- Messaging: NATS and RabbitMQ. Streams, publish, and a peek at what is waiting.
- Object store: Garage, which speaks S3. Buckets and objects, upload and download, and signed share links that expire and can be revoked. Even a share link streams through Flui’s backend, so the store itself is never reachable from outside. Images, PDFs, plain text, audio and video open in the browser; anything else, web pages included, is downloaded.
- Search: OpenSearch. Indexes, mappings, queries and counts.
- Secrets: OpenBao. Browse a path, read a version, write one, undelete one.
You do not choose which console you get. Flui reads the engine the catalog manifest declared when the service was installed. Where an install declares no engine, Flui falls back to what it can recognise from the image name, and then from the settings the install carries.
Backup, disk and going back in time
Three more panels sit alongside the consoles, on the database side:
- Backup: a logical dump produced by the engine’s own tool and streamed to you, and a restore that runs that dump back into the live database. The restore overwrites what is there, and it says so before it asks you to confirm.
- Disk: how full the storage under the database is, with a near-full warning. The number is for the filesystem hosting the volume, because that is where the database actually stops.
- Point in time: where continuous backup is on, the window you can recover to, and a restore as of a moment. That restore never touches the source: it builds a fresh install and recovers into it, and you connect to the copy.
The same three have CLI equivalents: flui db dump,
flui db restore, flui db disk, flui db backup-status
and flui db pitr-restore.
Who may open one
Opening a console goes through the same access engine as every other route in the product. Four things follow from that:
- Ownership alone is not enough. A grant can select applications by owner, but owning one does not give you access to it. If nothing grants you access to that application, its console does not open, even though the record is yours.
- Revoked or narrowed grants apply here too. The console checks on every open, so a revoked grant closes it like every other door in the product.
- A key’s ceiling is checked before the record is loaded. An agent credential carries a ceiling: a limit on what it may do, whoever holds it. Flui checks that ceiling first, before it even looks the application up, so a narrowly scoped key held by an application’s own owner cannot open a query prompt its scopes never mention. Checking first also keeps that refusal safe: it can be specific about the key’s own limits without revealing whether the id you named exists.
- Applications the platform installed answer to the installation. Flui’s own workloads belong to nobody in particular. Their consoles open only to a principal holding authority over the whole installation, held globally and not narrowed to one cluster or one set of applications.
The check asks for the level that lets you change an application, not only see it, because one console gives you arbitrary queries, decrypted connection details and a restore. A viewer grant does not open a console; an operator grant does. The roles are the ones in Who can reach what.
Refusals that say nothing
Only one refusal tells you what happened: the application exists, and it is not yours to reach.
Every other refusal reads as an absence, in the same words. A console that is fenced off, an id that does not exist and an application with no recorded owner all read identically, and none of them repeats the id back to you. A refusal that names its reason tells a stranger that the id runs something here, and refusals that differ from each other can be told apart. Somebody guessing ids learns nothing from them.
Read-only by default
Every console defaults to read-only. A write has to be asked for explicitly.
On the relational console this is enforced at the database
session, not by watching for the word DELETE. Each query
opens a transaction, sets it read-only, applies the limits,
and then rolls back instead of committing. A statement that
tries to write fails at the engine, and nothing it did
survives, because the transaction is discarded either way.
Every query also has two more limits:
- A statement timeout of about 30 seconds. A missing
WHEREor an accidental cross join is cut off by the database instead of holding a connection open. - A row cap of about 1000 rows. The grid shows the first slice and tells you it was truncated. The console is for inspection, not for bulk export.
The other consoles follow the same rule in their own terms. Browsing only reads. A command runner passes through a read-only gate: commands are allowed while they are reads, and a write or destructive command (a flush, a delete, a topic removal) is refused unless the write path was asked for.
The reason is blast radius. The console is the everyday tool for checking something, and it should not be able to break what it inspects.
How it connects: the owner’s own credentials
To run anything, the console has to authenticate to the service. It uses the service’s own owner credentials: the same user, password and database the catalog generated when it installed the building block.
You never type them and they are never stored a second time. Flui reads them at the moment of the query from the secret the install already owns. Relational engines carry a user and a database. Caches authenticate with a password alone, and are often installed with no authentication at all, in which case the console connects anonymously.
This means everyone who can open a console connects as the owner of that service. Flui accepts that because the default is read-only, opening a console requires a grant, and every query is recorded on the server, allowed and refused alike. It is still a limitation.
One narrow seam
One narrow piece, a connection resolver, turns “this
application” into a live connection. It resolves the owner
credentials and reports the role as owner. The query
layer, the transport and the helper above it never handle
credentials themselves.
How the browser reaches a private database
Flui databases are not reachable from outside the cluster network, so a console in your browser goes through Flui’s backend. The browser talks only to the Flui API. The backend opens a private link to the running database, runs the query over it and returns the result. The link stays open for about a minute so a burst of queries reuses it, then it closes. The browser never holds a connection to the database and never learns its address.
For the same reason, the connection-details panel is safe. It returns what you need to reason about a connection (engine, database name, user, port) and never the password, which does not travel over the API at all.
For a native client, flui db tunnel does the same on your
own machine: a local port, bound to loopback, forwarded
through the control plane, with nothing opened to the
internet. See
Open a database from your machine.
Two things it does not open
Two databases under the product are always closed to the web console. One is Flui’s own database, which holds every user, key, encrypted provider token and application record. The other is the identity provider’s tables, which live in the same place, so access there would open every session and credential on the installation.
That exclusion is declared in one place, with its reason next to it, and it does not depend on anything that could go missing: no label, no declared engine, no recorded owner. Taking a database out of it means deleting that line.
They are still reachable from the CLI, by someone holding authority over the whole installation. Because the stakes are higher, that has its own task page: Reach the platform’s own database.
The helper is data-blind
Most consoles offer a helper: describe what you want in plain words, and it writes the query or the command, with an explanation, for you to read and run yourself. It never runs anything for you, and it never sees your data.
What is sent to the model is structure and your question. On the relational console that means table and column names, types, primary keys and foreign keys, your prompt, and Flui’s own built-in notes on that engine’s dialect and its pitfalls. On the key-value console it is narrower: a key count and a breakdown by type, never key names or values. On the document and search consoles it is names, field paths and inferred types, never the contents of a record. On Kafka it is topic and group names, never a message.
Row data is never sent. The helper reads the shape of the data and does not read, sample or forward what is stored. That is what makes it safe to point a hosted model at a production database.
Whatever the helper writes then runs under the same rules as a hand-typed query: read-only by default, the timeout, the row cap. A suggestion that would change data is flagged so the dashboard can ask for confirmation, but the flag is only a hint. The read-only session underneath is the real boundary.
The helper has no model of its own. It uses the same inference layer as Flui’s other assistant features, so it uses whatever you configured there: Flui’s native inference or your own provider. See Inference and bring-your-own LLM.
What it is for
- It is a fast, safe way to look inside the data services you already run on Flui (query, browse, scan, read a value, get a draft) without exposing anything and without a second tool to host.
- It is not an administration suite, a migration runner or a bulk-export tool. The row cap and the read-only default make it the right thing to reach for first.
Where to read next
- Open a database from your machine:
flui db tunneland a native client. - Reach the platform’s own database: the two reserved names, and the rules around them.
- Who can reach what: the roles and grants a console asks about.
- The app concept: databases are applications in Flui’s model, with the same lifecycle, logs and metrics as anything else.
- Catalog vs application: where the building blocks these consoles operate on come from.
- Inference and bring-your-own LLM: the inference layer the data-blind helper draws on.