Skip to main content
Bifrost persists two types of data - config (providers, virtual keys, governance rules) and logs (request/response records). Each has its own store. A vector store is required for semantic caching.
If you use PostgreSQL for any store, the target database must be UTF8 encoded. See PostgreSQL UTF8 Requirement.

config_store

When config_store is omitted, Bifrost creates a default SQLite config store in the app directory. Set config_store.enabled to false only when you want file-only configuration with no config-backed Web UI/API edits. See Source of Truth & Reconciliation.

SQLite (Default)

Simplest setup - no external database required. Bifrost stores configuration in a local SQLite file.

logs_store

SQLite

Log Retention

Set retention_days to automatically purge old log entries. 0 disables retention-based cleanup.

Materialized View Refresh Interval (PostgreSQL only)

The PostgreSQL logs store backs the dashboard’s stats and histograms with materialized views, refreshed in the background. The default cadence is 1 minute, which keeps dashboard data near real-time but issues a REFRESH MATERIALIZED VIEW CONCURRENTLY every minute — an expensive operation that can be too aggressive on smaller or CPU-constrained database instances. Set matview_refresh_interval (Go duration string) to slow down refreshes when near-real-time accuracy isn’t critical:
Notes
  • Refreshes are already activity-gated: when no INSERT/UPDATE/DELETE has hit the logs table since the last refresh, the scheduled tick short-circuits without touching the views. So idle clusters don’t pay for the configured cadence — they only pay when there’s actual log activity.
  • Dashboard freshness lag will be at most the configured interval. Stats and histograms over the last 24 hours come straight from the raw logs table (no matview), so short-window dashboards stay real-time regardless of this setting.
  • A 10-minute safety-net refresh runs even on totally idle clusters so the rolling 30-day filter dropdown window evicts aged-out values.
When to raise it:
  • Your database instance is CPU-constrained and matview refreshes are showing up as a hot consumer.
  • Your team mostly looks at multi-day trends, not minute-by-minute dashboards.
When to leave it at the default:
  • The database has consistent CPU headroom.
  • Operators rely on near-real-time dashboards (e.g. live incident triage).
When to turn it off:
  • You don’t use the Bifrost dashboard (e.g. Bifrost runs headless behind your own observability stack). With "off", the views are neither created nor refreshed, and any dashboard query transparently uses the raw tables.

Object Storage for Logs

Offload LLM request/response logs and MCP tool logs from the database to S3 or GCS. The database retains lightweight index records and fetches full payloads on demand. For MCP logs, the full tool log is stored in object storage and the database keeps dashboard/table fields plus a 200-character input preview.

Required IAM Permissions

The IAM user or role needs the following permissions on your bucket:
IAM role (instance profile / IRSA) - omit access_key_id and secret_access_key:
  1. Attach this IAM policy to whichever AWS principal Bifrost authenticates as: the IAM user behind access_key_id/secret_access_key, or the IAM role behind role_arn:
  1. If you’re using a customer-managed key (not the AWS-managed aws/s3 key), it also needs permission granted separately on the key’s own policy (in the KMS console). Add that same IAM user or role ARN there too (AWS guide). AWS-managed keys don’t allow their key policy to be edited, so this step doesn’t apply if you’re using the default aws/s3 key.
Default encryption applies KMS without requiring encryption headers from the uploader. Bifrost’s IAM identity still needs the KMS permissions above regardless of encryption mode. If instead your bucket policy denies uploads that don’t include the encryption header, note that Bifrost does not send that header, so uploads will fail under that policy.

vector_store

A vector store is required for semantic caching. Choose from Weaviate, Redis/Valkey, Qdrant, or Pinecone.

Mixed Backend Example

Run the config store on PostgreSQL (for UI) while keeping logs on SQLite (simpler, cheaper for append-heavy workloads):

Full Storage Example