$ aoox

DocsStacks & databases

Data browser

Browse table contents, run queries, and export/import SQL directly from the dashboard — no extra database client needed.

Where
Database page → Data tab
Can do
View/edit/delete rows, table structure, queries, CSV, SQL export/import
Limits
500 rows, 15 seconds, 60 queries/min, 50-entry history

Layout

  1. 01leftlist of tables (or Redis keys) + an approximate row count
  2. 02top rightrow grid, 50 per page, click a header to sort, Structure tab
  3. 03bottom rightquery box — Ctrl+Enter to run, History tab
  4. 04toolbarpick a database, reload, Export CSV/SQL, Import SQL

For servers with more than one database, the Database select in the toolbar picks which one is shown. Creating or dropping extra databases is done on the Overview tab (owner/admin).

Running queries

EngineWhat runsExample
PostgreSQLA single SQL statement via psqlSELECT id, email FROM users ORDER BY id DESC
MySQL / MariaDBA single SQL statement via mysqlSHOW CREATE TABLE orders
RedisA single command via redis-cliHGETALL session:abc
  • Only one statement per query — a ; outside quotes is rejected (400). -- and /* */ comments are stripped first.
  • A SELECT/WITH without a LIMIT gets wrapped in LIMIT 501: at most 500 rows are displayed, marked as truncated. Add your own LIMIT/OFFSET to page through more.
  • A 15-second engine timeout (statement_timeout / max_execution_time / max_statement_time).
  • Results distinguish NULL from an empty string; non-SELECT statements return the engine's message, e.g. UPDATE 3.
  • Rate limit: 60 queries per minute per user.

Editing & deleting rows, table structure

The grid isn't just a viewer — cells can be edited directly, and every row has a Delete action (owner/admin). The Structure tab next to the grid shows a table's columns and indexes without needing \d or SHOW COLUMNS.

  • Every write is validated, not trusted: the WHERE clause must be exactly the table's primary key — no more, no less — and the columns being changed are matched against the table's real columns (not an identifier regex), so a column named first name still works.
  • Tables without a primary key reject edits/deletes (400) instead of silently writing to the whole table.
  • After writing, the API confirms exactly one row changed — from Postgres's command tag, or SELECT ROW_COUNT() in the same session for MySQL/ MariaDB. A stale primary key (the row was deleted elsewhere) produces a 400, not a false success.
  • Owner/admin only — members stay read-only, same as queries.

Write access per role

RoleAllowedGuardrail
memberStatements starting with SELECT, WITH, SHOW, EXPLAIN, DESCRIBE, VALUES, TABLE.Anything else → 403, and the engine session is put into read-only mode (default_transaction_read_only / SET SESSION TRANSACTION READ ONLY) — even WITH … DELETE fails at the engine.
owner / adminINSERT, UPDATE, DELETE, DDL, plus SQL import and creating databases.None — use with care; there's no undo.

Redis: members may only run read commands (GET, MGET, HGET*, LRANGE, SMEMBERS, ZRANGE, SCAN, …).

CSV export, SQL export & import

  1. Export CSV per table (all roles)

    The Export CSV button in the grid downloads the currently open table as .csv — good for spreadsheets, unlike a SQL dump which covers the whole database.

  2. Export SQL (all roles)

    The Export SQL button in the toolbar downloads a plain-text dump of the currently selected database (<slug>[-db].sql). Handy for moving data elsewhere or inspecting the structure.

  3. Import SQL (owner/admin)

    The Import SQL button accepts a .sql file up to 64 MB and runs it as-is against the selected database — after confirmation. The table list reloads automatically.

Imports aren't wrapped in a transaction and there's no undo. For important data, take a backup first. Redis has no CSV/SQL export — use backups instead.

Query history

The History tab keeps up to the last 50 queries per user per database — both successful and failed, so "what did I just run" is always complete. This is a separate table, not part of the instance audit log.

How it works

Every query runs in a one-off container from the same engine image (the same pattern backups use), with credentials passed via env and output written to a file and read back. The API doesn't bundle any database driver.

psql --csv  ·  mysql --batch  ·  redis-cli --json

Common pitfalls

SymptomCause & fix
400: only one statementThere's a trailing ; or multiple statements. Run them one at a time, or use Import SQL.
403 as a memberA write statement. Ask an owner/admin, or run it via an application migration (job).
Query stops at 15 secondsAdd an index/WHERE clause, or run it from the application. The timeout can't be raised from the UI.
Result truncated at 500 rowsUse LIMIT/OFFSET or export via SQL.
Import fails partway throughEarlier statements already ran. Restore a backup, fix the file, and try again.
400 when editing/deleting a rowThe table has no primary key, or that row already changed/was deleted elsewhere since the grid loaded. Reload and try again.

Next steps

Found a mistake? Edit this page on GitHub ↗