Skip to content

MongoDB

MongoDB holds everything Watcher needs to survive a restart. A free shared tier is enough for personal use.

.env
MongoDB_URI=<your-connection-string>

Use the full connection string from your provider. If you use a hosted cluster, add the IP addresses that will connect — including your CI runners — to its network access list, or connections fail with a server-selection timeout.

Watcher connects once at startup and fails fast with an actionable message if it cannot, rather than starting up half-working.

Collection Contents Grows with
watches Watch definitions Number of watches
run_state Per-watch memory: seen content, notified events, recent embeddings, the event ledger, pending deliveries Content volume
run_history One record per run Runs — the fastest-growing collection
trust_registry Your domain-to-tier rules Rules
device_tokens Push registrations Devices
api_keys, key_audit Encrypted keys and write audit Keys
key_category_config Model choice per use case At most a handful
key_usage Daily usage ledger Expires automatically after about 90 days
users Accounts (unique email index) Users
  • Encrypted: stored API keys, using a master key that lives only in the environment. The database never holds plaintext key material.
  • Hashed: account passwords. There is no way to recover the original.
  • Plain: watch definitions (including your conditions), run history (including collected evidence quotes and URLs), and trust rules.

Treat a database dump as sensitive: it contains what you watch and what Watcher found.

Free tiers typically do not back up for you. Watch definitions can be re-imported from YAML, but run state and history cannot be reconstructed — losing run state means Watcher forgets what it already told you, and the next run may re-alert past events.

See Backup and restore for a working weekly dump and the restore procedure.

At startup it makes a best-effort attempt to create:

  • a unique index on user email,
  • an expiry index on the usage ledger.

If the connecting user lacks permission, startup still succeeds — uniqueness then rests on an application-level check, and usage buckets simply do not expire.