Open Form

open-form db

See which database stores this workspace's responses and whether it answers, and copy a SQLite database into Postgres.

npx open-form db status
npx open-form db copy

db status

Reads the same settings as open-form start and connects once:

  ┃  Storage   Postgres (from OPEN_FORM_DATABASE_URL)
  ┃  Database  postgres://forms:***@db.example.com:5432/app?sslmode=verify-full
  ┃  Status    ✔ connected PostgreSQL 16.4 · schema open_form · migration 1
  ┃  Responses contact 12 · meetup 87
RowMeaning
StorageSQLite or Postgres, and the setting that chose it: OPEN_FORM_DATABASE_URL, storage.url, OPEN_FORM_DB, storage.path, or the default .open-form/open-form.db.
DatabaseThe file, or the connection string with its password replaced by ***.
StatusWhether it answered, the database version, and the migration it's on. Connecting applies any migration that's missing, as starting the server would.
ResponsesThe count per form, including forms in forms/ that have none yet.

A SQLite file that doesn't exist yet is reported as not created; db status doesn't create it. When the database doesn't answer, the error is printed and the command exits with code 1, so you can run it before a deploy.

FlagDescription
--jsonPrint { kind, location, source, ok, created, info, responses, error } instead.

db copy

Copies the workspace's SQLite database into the Postgres database that OPEN_FORM_DATABASE_URL (or storage.url) points at:

npx open-form db copy --dry-run
npx open-form db copy
  ┃  From      SQLite .open-form/open-form.db
  ┃  To        Postgres postgres://forms:***@db.example.com:5432/app?sslmode=verify-full
  ┃  Responses 99 (contact 12 · meetup 87)
  ┃  Settings  Studio settings of meetup
  ┃  Status    ✔ copied · the SQLite file keeps its own copy

Everything comes across as it was: each response with its id, number, submission time and language, the schema versions they were submitted under, each form's response numbering (the next response to a form whose newest was #87 is #88, even if #87 was deleted), the unique keys behind uniqueBy, Studio's settings (schedule, time zone, response caps, closed, published) and signed-out Studio sessions. Rate-limit counters stay behind; they reset within minutes anyway.

  • One transaction. Either everything is copied or nothing is. Responses submitted to Postgres while it runs wait for it, then land after the copied ones.
  • Into an empty database only. If Postgres already has responses, response numbers or Studio settings, db copy stops and writes nothing, so running it twice can't duplicate anything. Form versions a dev server already recorded there are reused.
  • The SQLite file stays. Nothing is deleted from it. Studio and every command read Postgres from now on; keep the file as a backup or delete it yourself.
FlagDescription
--from <file>The SQLite file to copy, relative to the workspace. Default: the one the workspace uses without Postgres (OPEN_FORM_DB, storage.path, else .open-form/open-form.db).
--dry-runCount what would be copied, without connecting to Postgres.

To store responses in Postgres, see Postgres.

On this page