Skip to main content
PostgreSQL is optional. Leave FIREFLO_DB_URL unset and FireFlo runs on file configuration with call records written to data/cdr/. Only two features require it: the CDR expiry sweep, which needs to query for records with no outcome, and prepaid credit, since credit can only enter through the database. Rating, least-cost routing and CDRs all work without one. So does the control panel’s read-only half — but the panel edits configuration, and in file mode there is nothing for it to edit.

Connection

FIREFLO_CONFIG_IMPORT is separate from FIREFLO_DB_MIGRATE on purpose: one applies forward-only DDL, the other replaces the rules that decide what customers are charged. --dry-run ignores it.

The source switch

One switch moves every domain at once. Set through the environment as FIREFLO_CONFIG_SOURCE.
Switching to db against an empty schema refuses every bind and every REST call at once. The credential loader publishes the empty map rather than ignoring it, so there is no fallback to the file. Fill the schema with fireflo import first.
Upgrading from before 0.5. This key replaced smsg.credentials.source, smsg.routing.source, smsg.rates.source and smsg.properties.source, and their FIREFLO_*_SOURCE variables. Those keys no longer do anything, so the gateway refuses to start while one of the variables is still set, rather than reverting that domain to a file in silence. Replace all four with FIREFLO_CONFIG_SOURCE.

The tables

A worker’s properties are projected onto outSms.instance.<name>.<key> and published exactly like app_config rows, so the fallback tier and live retuning are unaffected. Keep a setting in one place or the other — if both define the same key the worker table wins and the duplicate is logged.
A missing or disabled filter skips every rule that references it, rather than loading the rule with fewer conditions. Dropping a condition would make the rule match more traffic, so the failure would be silent and would route or price the wrong things.

What changes when you are in db mode

  • A change takes up to one poll interval, against roughly 200 ms for a file edit.
  • A failed read retains the previous configuration rather than blanking it.
  • Changes are announced exactly as a file edit is, so editing app_config retunes running workers — tps, maxRetries, pause, registered TLVs — and setting outSms.instance.<x>.enable to false stops that vendor within one interval.
  • Deleting a row reverts the key to whatever the next tier holds — an environment variable, or the coded default — rather than leaving it unset.
  • Every file watcher stands down. conf/smsg.properties is still read at startup.
app_route and app_rate from the pre-normalised schema are still read when the normalised tables are empty, with a warning. Nothing is converted automatically — the packed rule_line cannot be split in SQL.

Schema versioning

The schema is one baseline file, V1.19.0__baseline.sql, generated rather than hand-merged: the originals were applied to a scratch database, dumped with pg_dump --schema-only, and the dump verified by applying it to a second database and diffing the two. Later changes carry on at V1.20.0. Forward-only is the rule. It is numbered at the highest version it replaces, not the lowest, deliberately. A deployment that stopped part-way would treat a lower-numbered baseline as already applied and migrate to a no-op, silently missing whatever came after. At 1.19.0 it instead tries to apply and fails on the first table that already exists — recoverable, where the silent version corrupts by omission.
Migrations are forward-only. There are no undo scripts, so rolling back a schema change means restoring a backup. Take one before migrating a database you care about.
See fireflo db for test, migrate, info, validate and repair, and Choosing a configuration source for the migration path between file and database.