Skip to content

Release history

BetterDB-inc/monitor releases

Valkey-first observability with Redis compatibility. Query real-time metrics, analyze slow commands, detect hot keys, and investigate performance issues directly from AI coding assistants.

All releases

68 shown

Config change
semantic-cache-v0.5.1 Breaking

Telemetry required, opt-out supported

Config change
agent-cache-v0.6.1 Breaking

Mandatory telemetry

No immediate action
semantic-cache-py-v0.4.1 New feature

Observability + SemanticCache + Embedding helpers

No immediate action
semantic-cache-v0.4.1 Mixed

Cache harness + capability UI + Turbo bump

Config change
agent-cache-py-v0.6.1 Breaking
Auth

Required telemetry

Monitor
v0.22.0 Bug fix
Auth

MONITOR probe fixes

Config change
agent-v1.5.0 New feature
Auth Breaking upgrade

IAM auth for ElastiCache

Review required
v0.21.0 New feature
Crypto / TLS

MONITOR Capture Sessions, Anomaly Detection, Telemetry

Review required
semantic-cache-v0.5.0 Breaking risk
Auth RBAC

LLM-as-judge for cache hits

v0.20.0 New feature
Notable features
  • Diskless RDB transfer streams snapshot directly over TCP, removing disk space requirement on source for large datasets
  • Flush target checkbox clears every node of the target cluster before migration to avoid BUSYKEY errors
Full changelog

RedisShake migration options

Two new checkboxes added to the migration panel when DUMP/RESTORE or Online sync mode is selected:

  • Diskless RDB transfer — the source streams its RDB snapshot directly over TCP instead of writing it to disk first. Eliminates the need for free disk space equal to the dataset size on the source. Recommended for large datasets.
  • Flush target before migration — flushes every node of the target cluster before starting, preventing BUSYKEY errors when the target already contains data. In cluster mode each master is flushed individually (RedisShake's built-in option only flushed the seed node).

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.19.0...v0.20.0

v0.19.0 New feature
⚠ Upgrade required
  • Run `docker pull betterdb/monitor:latest` to upgrade.
  • `redis_shake` writer now emits `cluster = true` for cluster targets, fixing MOVED redirect handling.
  • Migration analysis aggregates DBSIZE and used_memory across all master shards in a Redis cluster.
Notable features
  • Added `redis_shake_sync` migration mode with two‑phase sync and brief read‑only cutover; option `preferReplica` defaults to false.
Full changelog

Added

redis_shake_sync migration mode. Uses RedisShake's sync_reader to open a PSYNC stream from the source. Phase 1 transfers the initial RDB snapshot to the target. Phase 2 replicates incremental writes continuously until you click Stop Migration to cut over. Brief read-only window at cutover instead of a full maintenance outage. Works for cross-engine migrations (Redis to Valkey) where the existing DUMP/RESTORE mode fails on RDB version mismatch.

One option exposed: preferReplica (default false). Read from a replica to avoid extra PSYNC load on the primary.

Fixed

  • Cluster writer for cluster targets. The existing redis_shake mode now correctly emits cluster = true on the writer when the target is a cluster. Previous releases hit MOVED redirects and exited with code 1.
  • Cluster totals in analysis. Migration analysis now aggregates DBSIZE and used_memory across all master shards. Previous releases reported one shard's totals as the cluster total.

Upgrade

docker pull betterdb/monitor:latest
v0.18.0 New feature
Notable features
  • Demo mode with `isDemo` flag, DemoModeGuard blocking mutations, and redesigned UI components
  • PostHog reverse proxy routing `/ingest/*` through the app domain to avoid ad blockers
Full changelog

What's New

Demo Workspace

Introduced a first-class demo mode that lets users try BetterDB without signing up.

  • New isDemo flag on tenants — provisioning a demo tenant creates a second Ingress rule, a Route53 CNAME alias, and sets DEMO_HOSTNAME / COOKIE_DOMAIN on the tenant pod
  • DemoModeGuard — mutations and sensitive reads (settings, webhooks, team) return 404 on the demo host
  • Frontend demo UIDemoContext, DemoBanner, and DemoGuardedRoute hide write actions and nav items (Team, Webhooks, Settings) in demo mode; locked items show as inactive with a tooltip
  • Redesigned NoConnectionsGuard empty state with an inline "or try live demo" CTA
  • Server-side PostHog telemetry for demo_workspace_loaded and demo_link_clicked events (bypasses ad blockers)

PostHog Reverse Proxy

PostHog analytics events are now routed through the app's own domain to avoid ad blocker interference.

  • NestJS controller handles /ingest/* in production via native fetch, forwarding to the configured POSTHOG_HOST
  • Vite dev server proxies /ingest to the PostHog EU region
  • Full unit and e2e test coverage for URL routing, body/header forwarding, and error handling

Provisioning Reliability

Several fixes to make tenant provisioning more resilient to retries.

  • 409 conflict handling now checks error.code in addition to error.statusCode / error.response.statusCode
  • Resource quotas are patched (not silently skipped) when they already exist
  • Ingress conflicts now patch the ALB group annotation so retries correctly move the ingress to the current ALB group
  • Docker build fixed: packages/shared/node_modules is now copied into the production image

MCP Cache Proposals

AgentTokenGuard is now wired into the CacheProposalsModule so MCP proposal endpoints are correctly protected in cloud mode.

Bug Fixes

  • Fixed tsconfig.build.json to exclude spec files from the NestJS production build
  • Fixed PostHog proxy global prefix exclusion (/ingest was being mounted under /api/ingest in production)

Infrastructure

  • Default provisioned image tag bumped to v0.18.0
  • Karpenter nodepool limits raised (CPU: 80→160, Memory: 200→400Gi) to support cluster growth

What's Changed

  • feature: add PostHog reverse proxy to bypass ad blockers by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/145
  • feat: demo workspace alias as a tenant flavor (v0.17.0) by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/150

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.17.1...v0.18.0

v0.17.1 Maintenance

Minor fixes and improvements.

Full changelog

Retriggering to fix build issue

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.17.0...v0.17.1

semantic-cache-py-v0.3.0 New feature
⚠ Upgrade required
  • Requires Valkey 8+ with the valkey-search module for vector index support
  • Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB
Notable features
  • SemanticCache API (initialize, check, store, batch lookup, invalidation, stats, threshold analysis)
  • Provider adapters for OpenAI, Anthropic, LlamaIndex, LangChain, LangGraph
  • Embedding helpers for OpenAI, Voyage AI, Cohere, Ollama, AWS Bedrock
Full changelog

betterdb-semantic-cache v0.1.0

Python port of @betterdb/semantic-cache. Embeddings-based semantic cache for AI
workloads backed by Valkey vector search — similarity matching, cost tracking,
multi-modal prompts, embedding cache, and threshold tuning, with built-in
OpenTelemetry and Prometheus instrumentation.

Requires Valkey 8+ with the valkey-search module (vector index support).
Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB.


Installation

pip install betterdb-semantic-cache

Optional extras install the provider SDKs alongside the library:

pip install "betterdb-semantic-cache[openai]"
pip install "betterdb-semantic-cache[anthropic]"
pip install "betterdb-semantic-cache[langchain]"
pip install "betterdb-semantic-cache[langgraph]"
pip install "betterdb-semantic-cache[llamaindex]"
pip install "betterdb-semantic-cache[httpx]"   # voyage / cohere / ollama embed helpers
pip install "betterdb-semantic-cache[bedrock]"  # AWS Bedrock embed helper

What's included

SemanticCache

| Method | Description |
|---|---|
| initialize() | Create or attach to the vector index |
| check(prompt) | Similarity lookup — returns hit/miss with confidence and optional cost saved |
| store(prompt, response) | Store a response with optional cost metadata |
| store_multipart(prompt, blocks) | Store structured content blocks |
| check_batch(prompts) | Pipelined batch lookup |
| invalidate(filter) | Delete entries matching a FT.SEARCH filter |
| invalidate_by_model(model) | Delete all entries for a model |
| invalidate_by_category(category) | Delete all entries in a category |
| stats() | Hit/miss counts and cumulative cost saved |
| index_info() | Index name, doc count, vector dimension |
| threshold_effectiveness() | Rolling window analysis and threshold recommendations |
| threshold_effectiveness_all() | Per-category analysis |
| flush() | Drop index and delete all cached entries |

Provider adapters

| Import | Provider |
|---|---|
| betterdb_semantic_cache.adapters.openai | OpenAI Chat Completions |
| betterdb_semantic_cache.adapters.openai_responses | OpenAI Responses API |
| betterdb_semantic_cache.adapters.anthropic | Anthropic Messages |
| betterdb_semantic_cache.adapters.llamaindex | LlamaIndex ChatMessage[] |
| betterdb_semantic_cache.adapters.langchain | LangChain BaseCache (async-only) |
| betterdb_semantic_cache.adapters.langgraph | LangGraph BetterDBSemanticStore |

Embedding helpers

| Import | Provider |
|---|---|
| embed.openai | OpenAI Embeddings API |
| embed.voyage | Voyage AI (httpx, no SDK required) |
| embed.cohere | Cohere Embed v3 (httpx, no SDK required) |
| embed.ollama | Ollama local models (httpx, no SDK required) |
| embed.bedrock | AWS Bedrock Titan / Cohere (boto3) |

Bundled default cost table

A default cost table sourced from LiteLLM's model_prices_and_context_window.json
is bundled and refreshed on every release. Cost savings tracking works out of the
box for 1,900+ models — no cost_table configuration required.

Observability

  • OpenTelemetry spans on every cache operation
  • Prometheus metrics: requests_total, similarity_score, operation_duration_seconds,
    embedding_duration_seconds, cost_saved_total, embedding_cache_total,
    stale_model_evictions_total

Cluster support

Pass a ValkeyCluster client and all SCAN-based operations (flush,
invalidate_by_model, invalidate_by_category) automatically iterate all master nodes.


Quick start

import asyncio
import valkey.asyncio as valkey
from betterdb_semantic_cache import SemanticCache, SemanticCacheOptions
from betterdb_semantic_cache.types import CacheStoreOptions
from betterdb_semantic_cache.embed.openai import create_openai_embed

client = valkey.Valkey(host="localhost", port=6379)
cache = SemanticCache(SemanticCacheOptions(
    client=client,
    embed_fn=create_openai_embed(),
    default_threshold=0.12,
))

async def main():
    await cache.initialize()

    result = await cache.check("What is the capital of France?")
    if result.hit:
        print("Cache hit:", result.response)
    else:
        answer = "Paris"  # ... call your LLM ...
        await cache.store(
            "What is the capital of France?", answer,
            CacheStoreOptions(model="gpt-4o", input_tokens=20, output_tokens=5),
        )

asyncio.run(main())

Full changelog

See CHANGELOG.md for detailed history.

semantic-cache-v0.4.0 New feature
⚠ Upgrade required
  • Existing `{prefix}:__config` keys now affect runtime thresholds; audit or disable config refresh with `configRefresh: { enabled: false }` if constructor values must remain authoritative.
  • New Prometheus counter `{prefix}_config_refresh_failed_total` tracks failed refresh attempts.
Notable features
  • Periodic config refresh every 30 seconds via `configRefresh` option; synchronous first refresh in `initialize()`; new `refreshConfig()` method returning a boolean.
  • `threshold_adjust` capability added to the discovery marker's capabilities array.
Full changelog

What's new

0.4.0

Added

  • Periodic config refresh - SemanticCache polls {prefix}:__config every 30s and updates defaultThreshold / categoryThresholds in-memory. First refresh fires synchronously on initialize() so a
    freshly-started process picks up an already-applied proposal immediately. Configure via the new configRefresh option; opt out with configRefresh: { enabled: false }. New Prometheus counter
    {prefix}_config_refresh_failed_total.
  • refreshConfig() - public method returning boolean for manual refresh.
  • threshold_adjust capability - added to the discovery marker's capabilities array.
  • ConfigRefreshOptions type exported from package root.

Changed

  • Constructor values for defaultThreshold and categoryThresholds are now used as fallbacks when the corresponding fields are absent from __config.

Behavior change

  • A {prefix}:__config Valkey hash that previously had no effect now drives defaultThreshold and categoryThresholds at runtime. Audit existing keys before upgrading, or set configRefresh: { enabled: false } to keep constructor values authoritative.

0.3.0

Added

  • Discovery marker protocol - on initialize() the cache registers itself in __betterdb:caches and writes a periodic __betterdb:heartbeat:<name> key (default 30s). Lets BetterDB Monitor enumerate live
    caches without manual config. New dispose() method. New discovery_write_failed_total Prometheus counter.

What's Changed

  • feature(semantic-cache): add discovery marker protocol (0.2.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/127
  • feature(agent-cache): add discovery marker protocol (0.5.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/128
  • feature: inference pipeline latency profiler by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/124
  • fix: remove hardcoded version strings from telemetry test files by @100NikhilBro in https://github.com/BetterDB-inc/monitor/pull/133
  • refactor(storage): extract WebhookRepository across all three storage adapters by @amitkojha05 in https://github.com/BetterDB-inc/monitor/pull/125
  • Infra/add additional ips for aws by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/144
  • fix: add @betterdb/shared path aliases to web tsconfig by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/146
  • feature(api): cache proposal data model + service + MCP propose tools by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/134

New Contributors

  • @100NikhilBro made their first contribution in https://github.com/BetterDB-inc/monitor/pull/133
  • @amitkojha05 made their first contribution in https://github.com/BetterDB-inc/monitor/pull/125

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.16.0...semantic-cache-v0.4.0

agent-cache-py-v0.6.0 New feature
⚠ Upgrade required
  • `ToolCache.load_policies()` now performs atomic swap instead of additive merge; externally deleted policies are evicted on next refresh
  • Discovery marker protocol added: caches register in `__betterdb:caches` and emit a heartbeat key every 30s, configurable via new `discovery` option
Notable features
  • Periodic config refresh via `config_refresh` option polls `{name}:__tool_policies` every 30s and atomically swaps the in-memory policy map
  • `ToolCache.refresh_policies()` public method added, returns bool for manual refresh
Full changelog

Added

  • Periodic config refresh - AgentCache polls {name}:__tool_policies every 30s and atomically swaps the in-memory policy map. Externally-applied changes (e.g. from BetterDB Monitor's cache proposal
    feature) take effect without a process restart. Configure via the new config_refresh option; opt out with config_refresh=ConfigRefreshOptions(enabled=False). New Prometheus counter
    {prefix}_config_refresh_failed_total.
  • ToolCache.refresh_policies() - public method returning bool for manual refresh.

Changed

  • ToolCache.load_policies() now performs an atomic swap rather than an additive merge - policies deleted externally (HDEL) are evicted from in-memory state on the next refresh.

0.5.0

Added

  • Discovery marker protocol - on construction, the cache registers itself in __betterdb:caches and writes a periodic __betterdb:heartbeat:<name> key (default 30s). Lets BetterDB Monitor enumerate live
    caches without manual config. New discovery option. New discovery_write_failed_total Prometheus counter. shutdown() stops the heartbeat.

agent-cache-v0.6.0 New feature
Notable features
  • Periodic config refresh polls `{name}:__tool_policies` every 30s and atomically swaps in-memory policy map; configurable via `configRefresh` option (opt-out with `enabled: false`).
  • `ToolCache.refreshPolicies()` public method for manual policy refresh returning a boolean.
Full changelog

What's new

0.6.0

Added

  • Periodic config refreshAgentCache polls {name}:__tool_policies every 30s and atomically swaps the in-memory policy map. Externally-applied changes (e.g. from BetterDB Monitor's cache proposal
    feature) take effect without a process restart. Configure via the new configRefresh option; opt out with configRefresh: { enabled: false }. New Prometheus counter {prefix}_config_refresh_failed_total.
  • ToolCache.refreshPolicies() — public method returning boolean for manual refresh.

Changed

  • ToolCache.loadPolicies() now performs an atomic swap rather than an additive merge — policies deleted externally (HDEL) are evicted from in-memory state on the next refresh.

0.5.0

Added

  • Discovery marker protocol — on construction, the cache registers itself in __betterdb:caches and writes a periodic __betterdb:heartbeat:<name> key (default 30s). Lets BetterDB Monitor enumerate live
    caches without manual config. New ensureDiscoveryReady() for strict name-collision enforcement. New ToolCache.listPolicyNames(). New discovery_write_failed_total Prometheus counter. shutdown() stops
    the heartbeat.

What's Changed

  • feature(semantic-cache): add discovery marker protocol (0.2.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/127
  • feature(agent-cache): add discovery marker protocol (0.5.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/128
  • feature: inference pipeline latency profiler by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/124
  • fix: remove hardcoded version strings from telemetry test files by @100NikhilBro in https://github.com/BetterDB-inc/monitor/pull/133
  • refactor(storage): extract WebhookRepository across all three storage adapters by @amitkojha05 in https://github.com/BetterDB-inc/monitor/pull/125
  • Infra/add additional ips for aws by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/144
  • fix: add @betterdb/shared path aliases to web tsconfig by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/146
  • feature(api): cache proposal data model + service + MCP propose tools by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/134

New Contributors

  • @100NikhilBro made their first contribution in https://github.com/BetterDB-inc/monitor/pull/133
  • @amitkojha05 made their first contribution in https://github.com/BetterDB-inc/monitor/pull/125

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.16.0...agent-cache-v0.6.0

mcp-v1.2.0 New feature
⚠ Upgrade required
  • All 14 cache‑intelligence tools now require the Pro tier feature flag `Feature.CACHE_INTELLIGENCE`
  • server.json must be updated to version 1.2.0 at upgrade time
Notable features
  • Added five cache‑intelligence approval tools (list, get, approve, reject, edit_and_approve) with `actor_source='mcp'` baked in
  • Updated server.json registry version to 1.2.0
Full changelog

What's new

Added

  • 5 cache-intelligence approval tools wrapping the existing approval HTTP endpoints with actor_source='mcp' baked in:
    • cache_list_pending_proposals - list pending proposals, optionally filtered by cache_name
    • cache_get_proposal - fetch a single proposal by id including its audit trail
    • cache_approve_proposal - synchronously approve and apply
    • cache_reject_proposal - reject with optional reason
    • cache_edit_and_approve_proposal - edit new_threshold or new_ttl_seconds and approve in one call (invalidate proposals are not editable)
  • README "Cache Intelligence Tools" section documenting all 14 cache tools (6 read-only + 3 propose + 5 approval) with example prompts.

Changed

  • server.json registry version synced to 1.2.0.

Pro tier - all 14 cache-intelligence tools require Feature.CACHE_INTELLIGENCE.

What's Changed

  • feature(semantic-cache): add discovery marker protocol (0.2.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/127
  • feature(agent-cache): add discovery marker protocol (0.5.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/128
  • feature: inference pipeline latency profiler by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/124
  • fix: remove hardcoded version strings from telemetry test files by @100NikhilBro in https://github.com/BetterDB-inc/monitor/pull/133
  • refactor(storage): extract WebhookRepository across all three storage adapters by @amitkojha05 in https://github.com/BetterDB-inc/monitor/pull/125
  • Infra/add additional ips for aws by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/144
  • fix: add @betterdb/shared path aliases to web tsconfig by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/146
  • feature(api): cache proposal data model + service + MCP propose tools by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/134

New Contributors

  • @100NikhilBro made their first contribution in https://github.com/BetterDB-inc/monitor/pull/133
  • @amitkojha05 made their first contribution in https://github.com/BetterDB-inc/monitor/pull/125

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.16.0...mcp-v1.2.0

v0.17.0 Breaking risk
Notable features
  • Cache Intelligence – full proposal lifecycle (propose, review, apply) with UI & API support
  • Inference Pipeline Latency Profiler – per‑bucket latency tiles, Prometheus metrics, and SLA features for Pro tier
Full changelog

[0.17.0] - 2026-05-05

Cache Intelligence - Full Proposal Lifecycle (Pro tier)

AI agents and operators can now propose, review, and apply cache-tuning changes end-to-end without a deployment.

Web UI

  • New Cache Proposals page in the sidebar (Pro-gated, with unread badge).
  • Pending view: per-proposal cards with one-click approve, reject, or inline edit-and-approve.
  • History view: full audit trail table with a detail panel showing every status transition.

API & Service

  • Complete proposal lifecycle: propose → approve / reject / edit-and-approve → apply.
  • Apply dispatcher writes approved threshold overrides directly to {prefix}:__config (semantic) or {name}:__tool_policies (agent) in Valkey - changes are live without a process restart.
  • Rate-limited proposals, idempotent approve, per-connection scoping, and automatic expiry cron.
  • Postgres and SQLite migrations for cache_proposals and cache_proposal_audit tables, with pending-deduplication, tenant-status-ordering, and expiry indexes.

MCP server - 14 cache-intelligence tools (Feature.CACHE_INTELLIGENCE)

  • 6 read-only: cache_list_caches, cache_health, cache_threshold_recommendation, cache_tool_effectiveness, cache_similarity_distribution, cache_recent_changes
  • 3 propose: cache_propose_threshold_adjust, cache_propose_tool_ttl_adjust, cache_propose_invalidate
  • 5 approve: cache_list_pending_proposals, cache_get_proposal, cache_approve_proposal, cache_reject_proposal, cache_edit_and_approve_proposal

On community-tier deployments the underlying endpoints return 402; no MCP-side gate is required.


Inference Pipeline Latency Profiler

New Inference Latency page (added to sidebar, requires Valkey Search) for diagnosing slow vector-search pipelines.

All tiers - live 15-minute window

  • p50/p95/p99 latency tiles per bucket: one per FT.SEARCH:<index>, plus aggregate read (GET/MGET) and write (SET/HSET-family).
  • Source advisory showing the active commandlog/slowlog directive and configured threshold, so percentiles can be qualified correctly.
  • Indexing-event correlation: raises a latency_degraded_during_indexing annotation when tail latency spikes coincide with a partially-indexed snapshot.
  • New Prometheus metrics: betterdb_inference_bucket_p50_us, betterdb_inference_bucket_p95_us, betterdb_inference_bucket_p99_us, betterdb_inference_unhealthy (per bucket),
    betterdb_inference_sla_breach (per index, Pro only).

Pro tier (INFERENCE_SLA)

  • Historical trend queries beyond the 15-minute window.
  • Configurable per-index p99 SLA thresholds via settings.
  • SLA debounce evaluation: fires only after a sustained breach, suppressing transient spikes.
  • New inference.sla.breach webhook event.

Cache Discovery Protocol

Monitor now auto-enumerates live @betterdb/semantic-cache (≥ 0.3.0) and @betterdb/agent-cache (≥ 0.5.0) instances via the __betterdb:caches Valkey registry - no manual configuration required. The
threshold_adjust capability flag gates apply-dispatcher writes.


SDK Releases (shipped alongside this version)

@betterdb/semantic-cache 0.4.0

  • Periodic config refresh: polls {prefix}:__config on a configurable interval (default 30s); first refresh fires synchronously on initialize().
  • New refreshConfig() public method and ConfigRefreshOptions export.
  • threshold_adjust capability added to the discovery marker.
  • Behavior change: a {prefix}:__config hash that previously had no effect now drives defaultThreshold / categoryThresholds at runtime. Set configRefresh: { enabled: false } to keep constructor
    values authoritative.

@betterdb/semantic-cache 0.3.0

  • Discovery marker protocol: registers in __betterdb:caches on initialize(), writes a 30s periodic heartbeat key. New dispose() method and discovery_write_failed_total Prometheus counter.

@betterdb/agent-cache 0.6.0

  • Periodic config refresh: polls {name}:__tool_policies every 30s with atomic-swap semantics (externally deleted policies are evicted locally).
  • New ToolCache.refreshPolicies() public method.

@betterdb/agent-cache 0.5.0

  • Discovery marker protocol: registers on construction, optional ensureDiscoveryReady() for strict collision enforcement. New ToolCache.listPolicyNames() and discovery_write_failed_total counter.

betterdb-agent-cache (Python) 0.5.0 → 0.6.0

  • Discovery marker protocol and periodic config refresh, matching the TypeScript releases.

Improvements

  • WebhookRepository extracted from all three storage adapters (Postgres, SQLite, in-memory) into dedicated repository classes, establishing the pattern for future domain extractions.

Bug Fixes

  • Fixed missing @betterdb/shared path aliases in the web app's tsconfig that caused build-time type errors (#146).
  • Removed hardcoded version strings from telemetry test files that caused false assertion failures on version bumps (#133).

What's Changed

  • feature(semantic-cache): add discovery marker protocol (0.2.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/127
  • feature(agent-cache): add discovery marker protocol (0.5.0) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/128
  • feature: inference pipeline latency profiler by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/124
  • fix: remove hardcoded version strings from telemetry test files by @100NikhilBro in https://github.com/BetterDB-inc/monitor/pull/133
  • refactor(storage): extract WebhookRepository across all three storage adapters by @amitkojha05 in https://github.com/BetterDB-inc/monitor/pull/125
  • Infra/add additional ips for aws by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/144
  • fix: add @betterdb/shared path aliases to web tsconfig by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/146
  • feature(api): cache proposal data model + service + MCP propose tools by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/134

New Contributors

  • @100NikhilBro made their first contribution in https://github.com/BetterDB-inc/monitor/pull/133
  • @amitkojha05 made their first contribution in https://github.com/BetterDB-inc/monitor/pull/125

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.16.0...v0.17.0

v0.16.0 Bug fix
⚠ Upgrade required
  • Re‑enable previously disabled TLS after upgrading; the connection form now strips http:// and https:// prefixes from pasted URLs.
Full changelog

Bug Fixes

TLS connections now work correctly

Connections configured with "Use TLS" were not actually establishing encrypted connections — the TLS flag was being saved to the database but silently ignored when connecting to Valkey/Redis. This affected any database that requires TLS, including
Upstash, Redis Cloud, Aiven, AWS ElastiCache with in-transit encryption, and self-managed instances with TLS enabled.

This is now fixed. If you previously worked around this by disabling TLS, you can re-enable it.

Connection form strips protocol prefixes automatically

Pasting a full URL (e.g. https://my-host.upstash.io) into the Host field would previously cause a DNS resolution failure. The form now automatically strips http:// and https:// prefixes, so you can paste connection strings directly from provider
dashboards without manually editing the host.

What's Changed

  • Semantic cache improvements by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/126
  • Semantic cache improvements by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/129
  • Semantic cache improvements by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/130
  • Semantic cache improvements by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/132
  • various fixes around deployment and provisioning after hitting AWS li… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/139

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.15.0...v0.16.0

semantic-cache-py-v0.1.3 New feature
⚠ Upgrade required
  • Requires Valkey 8+ with the valkey-search module (vector index support). Works with ElastiCache, Memorystore, and MemoryDB for Valkey.
Notable features
  • SemanticCache API (initialize, check, store, batch lookup, invalidation, stats, index info, threshold analysis, flush)
  • Provider adapters for OpenAI, Anthropic, LlamaIndex, LangChain, LangGraph
  • Embedding helpers for OpenAI, Voyage AI, Cohere, Ollama, AWS Bedrock
Full changelog

betterdb-semantic-cache v0.1.0

Python port of @betterdb/semantic-cache. Embeddings-based semantic cache for AI
workloads backed by Valkey vector search — similarity matching, cost tracking,
multi-modal prompts, embedding cache, and threshold tuning, with built-in
OpenTelemetry and Prometheus instrumentation.

Requires Valkey 8+ with the valkey-search module (vector index support).
Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB.


Installation

pip install betterdb-semantic-cache

Optional extras install the provider SDKs alongside the library:

pip install "betterdb-semantic-cache[openai]"
pip install "betterdb-semantic-cache[anthropic]"
pip install "betterdb-semantic-cache[langchain]"
pip install "betterdb-semantic-cache[langgraph]"
pip install "betterdb-semantic-cache[llamaindex]"
pip install "betterdb-semantic-cache[httpx]"   # voyage / cohere / ollama embed helpers
pip install "betterdb-semantic-cache[bedrock]"  # AWS Bedrock embed helper

What's included

SemanticCache

| Method | Description |
|---|---|
| initialize() | Create or attach to the vector index |
| check(prompt) | Similarity lookup — returns hit/miss with confidence and optional cost saved |
| store(prompt, response) | Store a response with optional cost metadata |
| store_multipart(prompt, blocks) | Store structured content blocks |
| check_batch(prompts) | Pipelined batch lookup |
| invalidate(filter) | Delete entries matching a FT.SEARCH filter |
| invalidate_by_model(model) | Delete all entries for a model |
| invalidate_by_category(category) | Delete all entries in a category |
| stats() | Hit/miss counts and cumulative cost saved |
| index_info() | Index name, doc count, vector dimension |
| threshold_effectiveness() | Rolling window analysis and threshold recommendations |
| threshold_effectiveness_all() | Per-category analysis |
| flush() | Drop index and delete all cached entries |

Provider adapters

| Import | Provider |
|---|---|
| betterdb_semantic_cache.adapters.openai | OpenAI Chat Completions |
| betterdb_semantic_cache.adapters.openai_responses | OpenAI Responses API |
| betterdb_semantic_cache.adapters.anthropic | Anthropic Messages |
| betterdb_semantic_cache.adapters.llamaindex | LlamaIndex ChatMessage[] |
| betterdb_semantic_cache.adapters.langchain | LangChain BaseCache (async-only) |
| betterdb_semantic_cache.adapters.langgraph | LangGraph BetterDBSemanticStore |

Embedding helpers

| Import | Provider |
|---|---|
| embed.openai | OpenAI Embeddings API |
| embed.voyage | Voyage AI (httpx, no SDK required) |
| embed.cohere | Cohere Embed v3 (httpx, no SDK required) |
| embed.ollama | Ollama local models (httpx, no SDK required) |
| embed.bedrock | AWS Bedrock Titan / Cohere (boto3) |

Bundled default cost table

A default cost table sourced from LiteLLM's model_prices_and_context_window.json
is bundled and refreshed on every release. Cost savings tracking works out of the
box for 1,900+ models — no cost_table configuration required.

Observability

  • OpenTelemetry spans on every cache operation
  • Prometheus metrics: requests_total, similarity_score, operation_duration_seconds,
    embedding_duration_seconds, cost_saved_total, embedding_cache_total,
    stale_model_evictions_total

Cluster support

Pass a ValkeyCluster client and all SCAN-based operations (flush,
invalidate_by_model, invalidate_by_category) automatically iterate all master nodes.


Quick start

import asyncio
import valkey.asyncio as valkey
from betterdb_semantic_cache import SemanticCache, SemanticCacheOptions
from betterdb_semantic_cache.types import CacheStoreOptions
from betterdb_semantic_cache.embed.openai import create_openai_embed

client = valkey.Valkey(host="localhost", port=6379)
cache = SemanticCache(SemanticCacheOptions(
    client=client,
    embed_fn=create_openai_embed(),
    default_threshold=0.12,
))

async def main():
    await cache.initialize()

    result = await cache.check("What is the capital of France?")
    if result.hit:
        print("Cache hit:", result.response)
    else:
        answer = "Paris"  # ... call your LLM ...
        await cache.store(
            "What is the capital of France?", answer,
            CacheStoreOptions(model="gpt-4o", input_tokens=20, output_tokens=5),
        )

asyncio.run(main())

Full changelog

See CHANGELOG.md for detailed history.

semantic-cache-py-v0.1.2 New feature
⚠ Upgrade required
  • Requires Valkey 8+ with the valkey-search module; works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB
  • Bundled default cost table refreshed on each release – no manual `cost_table` configuration needed
Notable features
  • SemanticCache class with initialize, check, store, batch lookup, invalidation, stats, threshold analysis, and flush methods
  • Provider adapters for OpenAI, Anthropic, LlamaIndex, LangChain (async), and LangGraph
  • Embedding helpers supporting OpenAI, Voyage AI, Cohere, Ollama, and AWS Bedrock
Full changelog

betterdb-semantic-cache v0.1.0

Python port of @betterdb/semantic-cache. Embeddings-based semantic cache for AI
workloads backed by Valkey vector search — similarity matching, cost tracking,
multi-modal prompts, embedding cache, and threshold tuning, with built-in
OpenTelemetry and Prometheus instrumentation.

Requires Valkey 8+ with the valkey-search module (vector index support).
Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB.


Installation

pip install betterdb-semantic-cache

Optional extras install the provider SDKs alongside the library:

pip install "betterdb-semantic-cache[openai]"
pip install "betterdb-semantic-cache[anthropic]"
pip install "betterdb-semantic-cache[langchain]"
pip install "betterdb-semantic-cache[langgraph]"
pip install "betterdb-semantic-cache[llamaindex]"
pip install "betterdb-semantic-cache[httpx]"   # voyage / cohere / ollama embed helpers
pip install "betterdb-semantic-cache[bedrock]"  # AWS Bedrock embed helper

What's included

SemanticCache

| Method | Description |
|---|---|
| initialize() | Create or attach to the vector index |
| check(prompt) | Similarity lookup — returns hit/miss with confidence and optional cost saved |
| store(prompt, response) | Store a response with optional cost metadata |
| store_multipart(prompt, blocks) | Store structured content blocks |
| check_batch(prompts) | Pipelined batch lookup |
| invalidate(filter) | Delete entries matching a FT.SEARCH filter |
| invalidate_by_model(model) | Delete all entries for a model |
| invalidate_by_category(category) | Delete all entries in a category |
| stats() | Hit/miss counts and cumulative cost saved |
| index_info() | Index name, doc count, vector dimension |
| threshold_effectiveness() | Rolling window analysis and threshold recommendations |
| threshold_effectiveness_all() | Per-category analysis |
| flush() | Drop index and delete all cached entries |

Provider adapters

| Import | Provider |
|---|---|
| betterdb_semantic_cache.adapters.openai | OpenAI Chat Completions |
| betterdb_semantic_cache.adapters.openai_responses | OpenAI Responses API |
| betterdb_semantic_cache.adapters.anthropic | Anthropic Messages |
| betterdb_semantic_cache.adapters.llamaindex | LlamaIndex ChatMessage[] |
| betterdb_semantic_cache.adapters.langchain | LangChain BaseCache (async-only) |
| betterdb_semantic_cache.adapters.langgraph | LangGraph BetterDBSemanticStore |

Embedding helpers

| Import | Provider |
|---|---|
| embed.openai | OpenAI Embeddings API |
| embed.voyage | Voyage AI (httpx, no SDK required) |
| embed.cohere | Cohere Embed v3 (httpx, no SDK required) |
| embed.ollama | Ollama local models (httpx, no SDK required) |
| embed.bedrock | AWS Bedrock Titan / Cohere (boto3) |

Bundled default cost table

A default cost table sourced from LiteLLM's model_prices_and_context_window.json
is bundled and refreshed on every release. Cost savings tracking works out of the
box for 1,900+ models — no cost_table configuration required.

Observability

  • OpenTelemetry spans on every cache operation
  • Prometheus metrics: requests_total, similarity_score, operation_duration_seconds,
    embedding_duration_seconds, cost_saved_total, embedding_cache_total,
    stale_model_evictions_total

Cluster support

Pass a ValkeyCluster client and all SCAN-based operations (flush,
invalidate_by_model, invalidate_by_category) automatically iterate all master nodes.


Quick start

import asyncio
import valkey.asyncio as valkey
from betterdb_semantic_cache import SemanticCache, SemanticCacheOptions
from betterdb_semantic_cache.types import CacheStoreOptions
from betterdb_semantic_cache.embed.openai import create_openai_embed

client = valkey.Valkey(host="localhost", port=6379)
cache = SemanticCache(SemanticCacheOptions(
    client=client,
    embed_fn=create_openai_embed(),
    default_threshold=0.12,
))

async def main():
    await cache.initialize()

    result = await cache.check("What is the capital of France?")
    if result.hit:
        print("Cache hit:", result.response)
    else:
        answer = "Paris"  # ... call your LLM ...
        await cache.store(
            "What is the capital of France?", answer,
            CacheStoreOptions(model="gpt-4o", input_tokens=20, output_tokens=5),
        )

asyncio.run(main())

Full changelog

See CHANGELOG.md for detailed history.

semantic-cache-py-v0.1.1 Maintenance

Minor fixes and improvements.

Changelog

Updated release flow

semantic-cache-py-v0.1.0 New feature
⚠ Upgrade required
  • Requires Python 3.11+ and Valkey 8+ with the `valkey-search` module installed
  • Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB
Notable features
  • Async‑first `SemanticCache` API with dataclass config and feature parity to the TypeScript version
  • Six provider adapters (OpenAI, Anthropic, LlamaIndex, LangChain, LangGraph) for extracting semantic cache keys
  • Embedding helpers for OpenAI, Voyage AI, Cohere, Ollama, AWS Bedrock
Full changelog

betterdb-semantic-cache v0.1.0

Initial release. Full Python port of @betterdb/semantic-cache v0.2.0 — async-first,
dataclass config, feature-for-feature parity with the TypeScript implementation.

Requires Python 3.11+, Valkey 8+ with the valkey-search module.
Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB.

Installation

pip install betterdb-semantic-cache

Install optional extras alongside the library:

pip install "betterdb-semantic-cache[openai]"
pip install "betterdb-semantic-cache[anthropic]"
pip install "betterdb-semantic-cache[langchain]"
pip install "betterdb-semantic-cache[langgraph]"
pip install "betterdb-semantic-cache[llamaindex]"
pip install "betterdb-semantic-cache[httpx]"     # Voyage AI, Cohere, Ollama
pip install "betterdb-semantic-cache[bedrock]"   # AWS Bedrock
pip install "betterdb-semantic-cache[all]"       # everything above

Adapters

Six adapters extract the semantic cache key from provider-specific request objects.
All return a SemanticParams dataclass with text, blocks, and model fields.

OpenAI Chat Completions

from betterdb_semantic_cache.adapters.openai import prepare_semantic_params

params = {
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "What is the capital of France?"}],
}
sp = await prepare_semantic_params(params)

result = await cache.check(sp.blocks or sp.text)
if not result.hit:
    response = await openai_client.chat.completions.create(**params)
    await cache.store(sp.blocks or sp.text, response.choices[0].message.content,
                      CacheStoreOptions(model=sp.model))

Handles text, image_url (URL and base64), input_audio, and file content parts.
Pass normalizer=cache.normalizer to share the same normalization strategy.

OpenAI Responses API

from betterdb_semantic_cache.adapters.openai_responses import prepare_semantic_params

sp = await prepare_semantic_params(params)
result = await cache.check(sp.blocks or sp.text)

Supports input_text, input_image, and input_file content parts.

Anthropic Messages

from betterdb_semantic_cache.adapters.anthropic import prepare_semantic_params

sp = await prepare_semantic_params(params)
result = await cache.check(sp.blocks or sp.text)

Supports text; base64, URL, and file images; base64, URL, plaintext, and file documents.

LlamaIndex

from betterdb_semantic_cache.adapters.llamaindex import prepare_semantic_params

sp = await prepare_semantic_params(messages, model="gpt-4o")
result = await cache.check(sp.text)

Extracts the last user ChatMessage from a list. Supports text, image_url,
file, audio, and image content parts.

LangChain — async BaseCache

BetterDBSemanticCache implements LangChain's BaseCache interface. Because
SemanticCache is async-only, the synchronous lookup() / update() methods
return None / no-op; use ainvoke / astream to get real cache behaviour.

from betterdb_semantic_cache.adapters.langchain import BetterDBSemanticCache
from langchain_openai import ChatOpenAI

lc_cache = BetterDBSemanticCache(cache)
llm = ChatOpenAI(model="gpt-4o", cache=lc_cache)

# Cache is transparent — hits are returned without calling the LLM
response = await llm.ainvoke("What is the capital of France?")

Optional filter_by_model=True scopes hits to a specific LLM configuration.

LangGraph semantic memory store

BetterDBSemanticStore implements the LangGraph BaseStore interface using
vector similarity for retrieval. Use this for agent memory (finding the most
relevant past facts for a query), not for checkpoint persistence — use
betterdb_agent_cache.adapters.langgraph for that. Both can coexist on the
same Valkey instance with different key prefixes.

from betterdb_semantic_cache.adapters.langgraph import BetterDBSemanticStore

store = BetterDBSemanticStore(cache, embed_field="content")

await store.aput(["user", "alice", "facts"], "pref_001", {
    "content": "Alice prefers async Python over synchronous code.",
})

results = await store.asearch(["user", "alice", "facts"],
                               query="What are Alice's coding preferences?",
                               limit=5)
# results[i].value — the stored dict; results[i].key — the item key

Full interface: aput(), aget(), asearch() (semantic KNN or namespace scan),
adelete(), abatch().


Embedding helpers

Five pre-built EmbedFn callables so you don't have to write your own:

| Import | Provider | Default model | Dimensions |
|---|---|---|---|
| betterdb_semantic_cache.embed.openai | OpenAI | text-embedding-3-small | 1536 |
| betterdb_semantic_cache.embed.voyage | Voyage AI | voyage-3-lite | 512 |
| betterdb_semantic_cache.embed.cohere | Cohere | embed-english-v3.0 | 1024 |
| betterdb_semantic_cache.embed.ollama | Ollama (local) | nomic-embed-text | 768 |
| betterdb_semantic_cache.embed.bedrock | AWS Bedrock | amazon.titan-embed-text-v2:0 | 1024 |

from betterdb_semantic_cache.embed.openai import create_openai_embed
from betterdb_semantic_cache.embed.voyage import create_voyage_embed
from betterdb_semantic_cache.embed.ollama import create_ollama_embed

cache = SemanticCache(SemanticCacheOptions(
    client=client,
    embed_fn=create_voyage_embed(model="voyage-3-lite"),
))

The Voyage AI, Cohere, and Ollama helpers use httpx directly — no provider SDK
required. The httpx client is created once per helper instance and reused across
calls. Install: pip install "betterdb-semantic-cache[httpx]".


Core features

Cost tracking + bundled model price table

Store token counts at cache time; get automatic cost-saved reporting on every hit.
A bundled DEFAULT_COST_TABLE covers 1,900+ models from
LiteLLM
and is refreshed on every release. No configuration required for common models.

await cache.store("Summarize this document", response_text,
                  CacheStoreOptions(model="gpt-4o", input_tokens=512, output_tokens=128))

result = await cache.check("Summarize this document")
print(result.cost_saved)        # e.g. 0.00385 — dollars saved on this hit

stats = await cache.stats()
print(stats.cost_saved_micros)  # cumulative across all hits

Override entries with cost_table={...}; disable with use_default_cost_table=False.

Multi-modal prompts

check(), store(), and store_multipart() accept str | list[ContentBlock].
A ContentBlock list embeds the text blocks and uses binary refs as an AND-filter —
a hit requires both semantic similarity on the text and all binary refs to match.

from betterdb_semantic_cache.normalizer import hash_base64
from betterdb_semantic_cache.utils import TextBlock, BinaryBlock

prompt = [
    TextBlock(type="text", text="What is in this image?"),
    BinaryBlock(type="binary", kind="image", mediaType="image/png",
                ref=hash_base64(b64_data)),
]

await cache.store_multipart(prompt, [TextBlock(type="text", text="A red square.")])
result = await cache.check(prompt)  # hit requires both text match AND same image
if result.hit:
    print(result.content_blocks)    # the stored ContentBlock[] response

Binary normalizer: compose_normalizer, hash_base64, hash_bytes, hash_url,
and fetch_and_hash generate stable, compact refs for any binary source. The
default_normalizer hashes base64 and bytes rather than storing raw data in TAG
fields. Access the configured normalizer via cache.normalizer.

Embedding cache

Computed embedding vectors are stored in Valkey ({name}:embed:{sha256}) and
reused on subsequent check() calls for the same text — embed_fn is only
called once per unique string.

SemanticCache(SemanticCacheOptions(
    ...,
    embedding_cache=EmbeddingCacheOptions(enabled=True, ttl=86400),  # default
))

Prometheus counter: {prefix}_embedding_cache_total labelled result: hit | miss.

Batch check — check_batch()

Embeds all prompts in parallel and pipelines all FT.SEARCH calls in a single
Valkey round-trip.

results = await cache.check_batch([
    "What is the capital of France?",
    "Who wrote Hamlet?",
    "What is the speed of light?",
])
# results[i] is a CacheCheckResult — same shape as check()

Rerank hook

Retrieve the top-k most similar candidates and apply custom ranking before
serving from cache.

async def pick_longest(_query: str, candidates: list[dict]) -> int:
    return max(range(len(candidates)), key=lambda i: len(candidates[i]["response"]))

result = await cache.check(query, CacheCheckOptions(
    rerank=RerankOptions(k=5, rerank_fn=pick_longest),
))

Return -1 from rerank_fn to reject all candidates (miss).

Stale-model eviction

Automatically evict cached entries when you upgrade the LLM for a prompt category.
On a hit, if the stored model differs from current_model, the entry is deleted and
the call returns a miss.

result = await cache.check(prompt, CacheCheckOptions(
    stale_after_model_change=True,
    current_model="gpt-4o",   # evict if entry was stored with gpt-3.5-turbo
))

Prometheus counter: {prefix}_stale_model_evictions_total.

Threshold effectiveness recommendations

threshold_effectiveness() analyzes a rolling window of cosine distance scores
(up to 10,000 entries, 7-day retention) and returns a concrete recommendation:

analysis = await cache.threshold_effectiveness(min_samples=100)
# ThresholdEffectivenessResult:
#   recommendation:         'tighten_threshold'
#   current_threshold:      0.1
#   recommended_threshold:  0.072
#   hit_rate:               0.83
#   uncertain_hit_rate:     0.31
#   reasoning:              '31.0% of hits are in the uncertainty band...'

all_results = await cache.threshold_effectiveness_all(min_samples=50)
# list[ThresholdEffectivenessResult] — one per category + aggregate

Params-aware filtering

temperature, top_p, and seed are stored as NUMERIC fields on entries,
enabling opt-in filtering when sampling parameters affect correctness.

await cache.store(prompt, response, CacheStoreOptions(temperature=0.0, seed=42))

result = await cache.check(prompt, CacheCheckOptions(
    filter="@temperature:[0 0] @seed:[42 42]",
))

PostHog analytics

Aggregate usage statistics (hit rate, cost saved per instance) are reported to
PostHog when the wheel is built with a baked API key. No prompt text, responses,
or PII are sent.

To opt out:

export BETTERDB_TELEMETRY=false   # also accepts: 0, no, off

Or programmatically:

from betterdb_semantic_cache.types import AnalyticsOptions

cache = SemanticCache(SemanticCacheOptions(
    ...,
    analytics=AnalyticsOptions(disabled=True),
))

Call await cache.shutdown() before process exit to flush queued events.


Full SemanticCache API

| Method | Description |
|---|---|
| await initialize() | Create or attach to the vector index |
| await check(prompt, opts?) | Similarity lookup — hit/miss with confidence, similarity score, optional cost saved |
| await store(prompt, response, opts?) | Store a response with optional cost metadata |
| await store_multipart(prompt, blocks, opts?) | Store a structured ContentBlock list as the response |
| await check_batch(prompts, opts?) | Pipelined multi-prompt lookup |
| await invalidate(filter) | Delete entries matching an FT.SEARCH filter |
| await invalidate_by_model(model) | Delete all entries tagged with a model name |
| await invalidate_by_category(category) | Delete all entries in a category |
| await stats() | Hit/miss counts and cumulative cost saved |
| await index_info() | Index name, doc count, vector dimension |
| await threshold_effectiveness(min_samples?) | Threshold tuning analysis |
| await threshold_effectiveness_all(min_samples?) | Per-category + aggregate analysis |
| await flush() | Drop index and delete all cached entries |
| await shutdown() | Stop stats timer and flush analytics queue |

Key SemanticCacheOptions fields

| Field | Default | Description |
|---|---|---|
| client | required | valkey.asyncio.Valkey or ValkeyCluster |
| embed_fn | required | Async callable (str) → list[float] |
| default_threshold | 0.1 | Cosine distance threshold (0–2, lower = stricter) |
| default_ttl | None | Entry TTL in seconds |
| category_thresholds | {} | Per-category threshold overrides |
| uncertainty_band | 0.05 | Distance band below threshold that returns confidence='uncertain' |
| use_default_cost_table | True | Merge bundled LiteLLM prices |
| embedding_cache | EmbeddingCacheOptions(enabled=True, ttl=86400) | Embed vector caching |
| normalizer | default_normalizer | Binary content normalizer (accessible as cache.normalizer) |
| analytics | AnalyticsOptions() | PostHog analytics config |


Observability

Seven Prometheus metrics, all labelled with cache_name:

| Metric | Labels | Description |
|---|---|---|
| {prefix}_requests_total | result, category | Hit / uncertain_hit / miss counts |
| {prefix}_similarity_score | category | Cosine distance histogram |
| {prefix}_operation_duration_seconds | operation | Per-operation latency |
| {prefix}_embedding_duration_seconds | — | embed_fn call latency |
| {prefix}_cost_saved_total | category | Dollars saved on hits |
| {prefix}_embedding_cache_total | result | Embedding cache hit / miss |
| {prefix}_stale_model_evictions_total | — | Stale-model eviction count |

OpenTelemetry spans are created for every cache operation with cache.hit,
cache.similarity, cache.threshold, cache.confidence, and cache.category
attributes. Pass a custom registry in TelemetryOptions to isolate metrics
from the host application's default registry.


12 runnable examples

examples/basic/            examples/openai/           examples/anthropic/
examples/llamaindex/       examples/langchain/         examples/langgraph/
examples/multimodal/       examples/cost_tracking/     examples/threshold_tuning/
examples/embedding_cache/  examples/batch_check/       examples/rerank/

Each requires only a local Valkey instance with valkey-search:

cd examples/basic && python main.py

Telemetry

The published wheel includes anonymous product analytics powered by PostHog.
Aggregate statistics (hit rate, cost saved) are collected on a per-instance basis
using a stable UUID persisted in Valkey — no prompt text, responses, or PII.

To opt out: export BETTERDB_TELEMETRY=false

See the Analytics section above for full details.


Links

semantic-cache-v0.2.0 Breaking risk
⚠ Upgrade required
  • Schema migration for multi‑modal features: call `flush()` then `initialize()` to add `binary_refs`, `temperature`, `top_p`, and `seed` fields; existing text‑only indexes remain functional.
  • Embedding cache enabled by default; can be tuned via `embeddingCache.ttl`.
Notable features
  • Five new adapters: OpenAI Chat Completions, OpenAI Responses API, Anthropic Messages, LlamaIndex, LangGraph semantic memory store.
  • Cost tracking with bundled model price table and automatic dollars‑saved reporting.
  • Multi‑modal prompts supporting text + binary references (images/audio/files) via `ContentBlock[]`.
Full changelog

Release Notes — @betterdb/semantic-cache v0.2.0

v0.1.0 shipped the core cache with text-only string prompts and two adapters.
v0.2.0 adds five new adapters, five embedding helpers, and a set of features
that make the cache production-ready: cost tracking, multi-modal prompts, batch
lookup, threshold tuning, embedding cache, stale-model eviction, and a rerank hook.

Installation

npm install @betterdb/[email protected] iovalkey

New adapters

v0.1.0 had LangChain and Vercel AI SDK. v0.2.0 adds:

OpenAI Chat Completions — @betterdb/semantic-cache/openai

Extracts the last user message from ChatCompletionCreateParams. Handles text,
image_url (URL and base64), input_audio, and file content parts.

import { prepareSemanticParams } from '@betterdb/semantic-cache/openai';

const { text, blocks, model } = await prepareSemanticParams(params);
const result = await cache.check(blocks ?? text);
if (!result.hit) {
  const response = await openai.chat.completions.create(params);
  await cache.store(blocks ?? text, response.choices[0].message.content!, { model });
}

OpenAI Responses API — @betterdb/semantic-cache/openai-responses

Extracts the last user input from the Responses API input field — string or
message array with input_text, input_image, and input_file parts.

import { prepareSemanticParams } from '@betterdb/semantic-cache/openai-responses';

const { text, blocks } = await prepareSemanticParams(params);
const result = await cache.check(blocks ?? text);

Anthropic Messages — @betterdb/semantic-cache/anthropic

Extracts the last user message from MessageCreateParamsNonStreaming. Supports
text; base64, URL, and file images; and base64, URL, plaintext, and file documents.

import { prepareSemanticParams } from '@betterdb/semantic-cache/anthropic';

const { text, blocks, model } = await prepareSemanticParams(params);
const result = await cache.check(blocks ?? text);

LlamaIndex — @betterdb/semantic-cache/llamaindex

Extracts the last user ChatMessage from a ChatMessage[] array. Supports
text, image_url, file, audio, and image content parts.

import { prepareSemanticParams } from '@betterdb/semantic-cache/llamaindex';

const { text } = await prepareSemanticParams(messages, { model: 'gpt-4o' });
const result = await cache.check(text);

LangGraph semantic memory store — @betterdb/semantic-cache/langgraph

BetterDBSemanticStore implements the LangGraph BaseStore interface using
vector similarity — find the most semantically relevant past observations for a
given query. This is distinct from @betterdb/agent-cache/langgraph, which does
exact-match checkpoint persistence. Both can coexist on the same Valkey instance
with different key prefixes.

import { BetterDBSemanticStore } from '@betterdb/semantic-cache/langgraph';

const store = new BetterDBSemanticStore({ cache, embedField: 'content' });

await store.put(['user', 'alice', 'facts'], 'pref_001', {
  content: 'Alice prefers async Python over synchronous code.',
});

const results = await store.search(['user', 'alice', 'facts'], {
  query: "What are Alice's coding preferences?",
  limit: 5,
});
// results[i].value — the stored object; results[i].key — the item key

Full interface: put(), get(), search() (semantic KNN or namespace scan),
delete(), batch().

Updated: LangChain — @betterdb/semantic-cache/langchain

BetterDBSemanticCache now wraps responses in a proper AIMessage so chat
models can correctly access response.content. New filterByModel option scopes
hits to a specific LLM configuration (deterministically hashed from llm_string).


Embedding helpers

Five pre-built EmbedFn factories so you don't have to write your own:

| Import | Provider | Default model | Dimensions |
|---|---|---|---|
| @betterdb/semantic-cache/embed/openai | OpenAI | text-embedding-3-small | 1536 |
| @betterdb/semantic-cache/embed/voyage | Voyage AI | voyage-3-lite | 512 |
| @betterdb/semantic-cache/embed/cohere | Cohere | embed-english-v3.0 | 1024 |
| @betterdb/semantic-cache/embed/ollama | Ollama (local) | nomic-embed-text | 768 |
| @betterdb/semantic-cache/embed/bedrock | AWS Bedrock | amazon.titan-embed-text-v2:0 | 1024 |

import { createOpenAIEmbed } from '@betterdb/semantic-cache/embed/openai';
import { createVoyageEmbed } from '@betterdb/semantic-cache/embed/voyage';
import { createOllamaEmbed } from '@betterdb/semantic-cache/embed/ollama';
import { createBedrockEmbed } from '@betterdb/semantic-cache/embed/bedrock';

const cache = new SemanticCache({
  client,
  embedFn: createVoyageEmbed({ model: 'voyage-3-lite' }),
});

All helpers lazily initialise their clients and cache the instance across calls —
no per-request connection overhead.


New core features

Cost tracking + bundled model price table

Store token counts at cache time; get automatic cost-saved reporting on every hit.
A bundled DEFAULT_COST_TABLE covers 1,971 models sourced from
LiteLLM
and is refreshed on every release via pnpm update:pricing. No configuration is
required for common models.

await cache.store('Summarize this document', responseText, {
  model: 'gpt-4o',
  inputTokens: 512,
  outputTokens: 128,
});

const result = await cache.check('Summarize this document');
console.log(result.costSaved);       // e.g. 0.00385 — dollars saved on this hit

const stats = await cache.stats();
console.log(stats.costSavedMicros);  // cumulative across all hits

Override or extend the table via costTable; disable it with
useDefaultCostTable: false. DEFAULT_COST_TABLE and ModelCost are exported
from the package root.

Multi-modal prompts

check(), store(), and the new storeMultipart() accept string | ContentBlock[].
A ContentBlock[] prompt embeds the text blocks and uses binary refs as an AND-filter —
a hit requires both the text to be semantically similar and all binary refs to
match exactly.

import { hashBase64, type ContentBlock } from '@betterdb/semantic-cache';

const prompt: ContentBlock[] = [
  { type: 'text', text: 'What is in this image?' },
  { type: 'binary', kind: 'image', mediaType: 'image/png', ref: hashBase64(b64) },
];

await cache.store(prompt, 'A red square on a white background.');
const result = await cache.check(prompt); // hit requires both text AND same image

storeMultipart(prompt, blocks[]) stores a structured response (text +
citations + tool calls) and returns result.contentBlocks on hit.

Binary normalizer: composeNormalizer, hashBase64, hashBytes, hashUrl,
and fetchAndHash produce stable, compact refs for any binary source. The
defaultNormalizer hashes base64 and bytes rather than storing raw data in TAG
fields. All normalizer utilities are exported from the package root.

Embedding cache

Computed embedding vectors are stored in Valkey ({name}:embed:{sha256}) and
reused on subsequent check() calls for the same text — embedFn is only
called once per unique string, then reads hit a fast GET.

// enabled by default; override if needed:
new SemanticCache({
  embeddingCache: { enabled: true, ttl: 86400 },
});

New Prometheus counter: {prefix}_embedding_cache_total labelled
result: hit | miss.

Batch check — checkBatch()

Embeds all prompts in parallel and pipelines all FT.SEARCH calls in a single
Valkey round-trip.

const results = await cache.checkBatch([
  'What is the capital of France?',
  'Who wrote Hamlet?',
  'What is the speed of light?',
]);
// results[i] is a CacheCheckResult — same shape as check()

Typically 60–80% faster than sequential check() calls for bulk lookups,
dashboards, and prefetch patterns.

Rerank hook

Retrieve the top-k most similar candidates and apply custom ranking before
deciding whether to serve from cache — useful for cross-encoder reranking,
LLM-as-judge, or domain-specific scoring.

const result = await cache.check(query, {
  rerank: {
    k: 5,
    rerankFn: async (query, candidates) => {
      const scores = await crossEncoder.predict(query, candidates.map(c => c.response));
      const best = scores.indexOf(Math.max(...scores));
      return scores[best] > 0.8 ? best : -1; // -1 → reject all → miss
    },
  },
});

Stale-model eviction

Automatically evict cached entries when you upgrade the LLM for a prompt category.
On a hit, if the stored model differs from currentModel, the entry is deleted and
the call returns a miss — forcing a fresh response under the new model.

const result = await cache.check(prompt, {
  staleAfterModelChange: true,
  currentModel: 'gpt-4o',  // evict if entry was stored with gpt-3.5-turbo
});

New Prometheus counter: {prefix}_stale_model_evictions_total.

Threshold effectiveness recommendations

The cache records a rolling window of cosine distance scores (up to 10,000
entries, 7-day retention). thresholdEffectiveness() analyzes this window and
returns a concrete recommendation:

const analysis = await cache.thresholdEffectiveness({ minSamples: 100 });
// {
//   recommendation: 'tighten_threshold',
//   currentThreshold: 0.1,
//   recommendedThreshold: 0.072,
//   hitRate: 0.83,
//   uncertainHitRate: 0.31,
//   nearMissRate: 0.04,
//   reasoning: '31.0% of hits are in the uncertainty band — tighten the threshold...',
// }

// Per-category + aggregate in one call:
const allResults = await cache.thresholdEffectivenessAll({ minSamples: 50 });

Possible recommendations: tighten_threshold, loosen_threshold, optimal,
insufficient_data.

Params-aware filtering

temperature, topP, and seed are stored as NUMERIC fields on entries,
enabling opt-in filtering when sampling params affect correctness.

await cache.store(prompt, response, { temperature: 0, seed: 42 });

const result = await cache.check(prompt, {
  filter: '@temperature:[0 0] @seed:[42 42]',
});

PostHog analytics

Aggregate usage statistics (hit rate, cost saved per instance) are reported to
PostHog when the wheel is built with a baked API key. No prompt text, responses,
or PII are ever sent.

To opt out:

export BETTERDB_TELEMETRY=false   # also accepts: 0, no, off

Or programmatically: new SemanticCache({ analytics: { disabled: true } }).

Call await cache.shutdown() before process exit to flush any queued events.


New SemanticCache API surface

| Addition | Description |
|---|---|
| check(ContentBlock[]) | Multi-modal prompt lookup |
| store(ContentBlock[]) | Multi-modal prompt storage |
| storeMultipart(prompt, blocks[]) | Store a structured ContentBlock[] response |
| checkBatch(prompts[]) | Pipelined multi-prompt lookup |
| invalidateByModel(model) | Delete all entries tagged with a model name |
| invalidateByCategory(category) | Delete all entries in a category |
| thresholdEffectiveness(opts?) | Rolling-window threshold tuning analysis |
| thresholdEffectivenessAll(opts?) | Per-category + aggregate threshold analysis |
| shutdown() | Stop stats timer and flush analytics queue |
| CacheCheckResult.contentBlocks | Structured response blocks on hit |
| CacheCheckResult.costSaved | Dollars saved (when cost metadata stored) |
| CacheCheckResult.nearestMiss | Similarity + delta for miss diagnostics |
| CacheCheckOptions.rerank | Top-k rerank hook |
| CacheCheckOptions.staleAfterModelChange | Auto-evict on model upgrade |
| CacheStoreOptions.inputTokens / outputTokens | For cost tracking |
| SemanticCacheOptions.embeddingCache | Embedding vector caching config |
| SemanticCacheOptions.categoryThresholds | Per-category threshold overrides |
| SemanticCacheOptions.uncertaintyBand | Controls uncertain vs high confidence |
| SemanticCacheOptions.analytics | PostHog analytics config |


13 runnable examples

examples/openai            examples/openai-responses   examples/anthropic
examples/llamaindex        examples/langchain           examples/langgraph
examples/vercel-ai-sdk     examples/multimodal          examples/cost-tracking
examples/threshold-tuning  examples/embedding-cache     examples/batch-check
examples/rerank

Each runs against a local Valkey instance with pnpm start. See
examples/README.md for setup instructions.


Breaking changes

None. String prompts produce byte-identical behavior to v0.1.0.

Schema migration for multi-modal features: The v0.2.0 index schema adds
binary_refs TAG, temperature NUMERIC, top_p NUMERIC, and seed NUMERIC
fields. Existing v0.1.0 indexes continue to work in text-only mode. To use the
new fields, call flush() then initialize() — this drops and rebuilds the index.


Links

What's Changed

  • Semantic cache improvements by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/126

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/agent-cache-py-v0.4.1...semantic-cache-v0.2.0

agent-cache-py-v0.4.1 New feature
Notable features
  • Three cache tiers: `cache.llm`, `cache.tool`, and `cache.session` for LLM responses, tool call results, and agent session state respectively.
  • Bundled default cost table covering ~1,900 models with automatic out‑of‑the‑box cost tracking; user overrides via `cost_table` and ability to disable defaults.
  • Pluggable binary normalizer allowing custom hashing of image/audio/document content before caching.
Full changelog

betterdb-agent-cache v0.4.0

Python port of @betterdb/agent-cache. Multi-tier exact-match cache for AI agent
workloads backed by Valkey — LLM responses, tool results, and session state, with
built-in OpenTelemetry and Prometheus instrumentation.

Runs on vanilla Valkey 7+. No modules, no RedisJSON, no RediSearch. Works on
ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB.


Installation

pip install betterdb-agent-cache

Optional extras install the provider SDKs alongside the library:

pip install "betterdb-agent-cache[openai]"
pip install "betterdb-agent-cache[anthropic]"
pip install "betterdb-agent-cache[langchain]"
pip install "betterdb-agent-cache[langgraph]"
pip install "betterdb-agent-cache[llamaindex]"

What's included

Three cache tiers

| Tier | Use for |
|---|---|
| cache.llm | LLM API responses — check / store / store_multipart / invalidate_by_model |
| cache.tool | Tool call results — check / store / set_policy / invalidate_by_tool |
| cache.session | Agent session state — get / set / get_all / destroy_thread / touch |

Provider adapters

| Import | Provider |
|---|---|
| betterdb_agent_cache.adapters.openai | OpenAI Chat Completions |
| betterdb_agent_cache.adapters.openai_responses | OpenAI Responses API |
| betterdb_agent_cache.adapters.anthropic | Anthropic Messages |
| betterdb_agent_cache.adapters.llamaindex | LlamaIndex |
| betterdb_agent_cache.adapters.langchain | LangChain BaseCache |
| betterdb_agent_cache.adapters.langgraph | LangGraph BaseCheckpointSaver |

Bundled default cost table

A default cost table sourced from LiteLLM's model_prices_and_context_window.json
is bundled with the package and refreshed on every release. Cost tracking works out of
the box for 1,900+ models — no cost_table configuration required.

User-supplied cost_table entries are merged on top of the defaults, so you can
override a single model without losing coverage for everything else:

cache = AgentCache(AgentCacheOptions(
    client=client,
    cost_table={"gpt-4o": ModelCost(input_per_1k=0.002, output_per_1k=0.008)},
))

To disable the default table entirely:

cache = AgentCache(AgentCacheOptions(
    client=client,
    use_default_cost_table=False,
    cost_table={...},
))

The bundled table is also exported directly if you need to inspect it:

from betterdb_agent_cache import DEFAULT_COST_TABLE

Pluggable binary normalizer

Controls how binary content (images, audio, documents) is reduced to a stable string
before hashing. Zero-latency by default — no network calls.

from betterdb_agent_cache import compose_normalizer, hash_base64

normalizer = compose_normalizer({"base64": hash_base64})

Observability

  • OpenTelemetry spans on every cache operation
  • Prometheus counters, histograms, and gauges: requests_total, operation_duration_seconds,
    cost_saved_total, stored_bytes_total, active_sessions

Cluster support

Pass a ValkeyCluster client and all SCAN-based operations (flush, invalidate_by_model,
invalidate_by_tool, destroy_thread, touch) automatically iterate all master nodes.


Quick start

Cost tracking is pre-defined for 1,900+ models — no pricing configuration needed.

import asyncio
import valkey.asyncio as valkey_client
from betterdb_agent_cache import AgentCache, TierDefaults
from betterdb_agent_cache.adapters.openai import prepare_params
from betterdb_agent_cache.types import AgentCacheOptions

client = valkey_client.Valkey(host="localhost", port=6379)
cache = AgentCache(AgentCacheOptions(
    client=client,
    tier_defaults={"llm": TierDefaults(ttl=3600)},
    # cost_table is pre-defined for GPT-4o, Claude, Gemini, and 1,900+ others
))

async def main():
    params = await prepare_params({
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": "What is 2+2?"}],
    })

    result = await cache.llm.check(params)
    if result.hit:
        print("Cache hit:", result.response)
    else:
        # ... call OpenAI ...
        await cache.llm.store(params, "Four")

asyncio.run(main())

Full changelog

See CHANGELOG.md for detailed history.

agent-cache-py-v0.4.0 New feature
Notable features
  • Three cache tiers: `cache.llm` for LLM API responses, `cache.tool` for tool call results, and `cache.session` for agent session state
  • Provider adapters for OpenAI Chat Completions, OpenAI Responses API, Anthropic Messages, LlamaIndex, LangChain BaseCache, and LangGraph BaseCheckpointSaver
  • Pluggable binary normalizer via `compose_normalizer` and built‑in `hash_base64`
Full changelog

betterdb-agent-cache v0.3.0

Python port of @betterdb/agent-cache. Multi-tier exact-match cache for AI agent
workloads backed by Valkey — LLM responses, tool results, and session state, with
built-in OpenTelemetry and Prometheus instrumentation.

Runs on vanilla Valkey 7+. No modules, no RedisJSON, no RediSearch. Works on
ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB.


Installation

pip install betterdb-agent-cache

Optional extras install the provider SDKs alongside the library:

pip install "betterdb-agent-cache[openai]"
pip install "betterdb-agent-cache[anthropic]"
pip install "betterdb-agent-cache[langchain]"
pip install "betterdb-agent-cache[langgraph]"
pip install "betterdb-agent-cache[llamaindex]"

What's included

Three cache tiers

| Tier | Use for |
|---|---|
| cache.llm | LLM API responses — check / store / store_multipart / invalidate_by_model |
| cache.tool | Tool call results — check / store / set_policy / invalidate_by_tool |
| cache.session | Agent session state — get / set / get_all / destroy_thread / touch |

Provider adapters

| Import | Provider |
|---|---|
| betterdb_agent_cache.adapters.openai | OpenAI Chat Completions |
| betterdb_agent_cache.adapters.openai_responses | OpenAI Responses API |
| betterdb_agent_cache.adapters.anthropic | Anthropic Messages |
| betterdb_agent_cache.adapters.llamaindex | LlamaIndex |
| betterdb_agent_cache.adapters.langchain | LangChain BaseCache |
| betterdb_agent_cache.adapters.langgraph | LangGraph BaseCheckpointSaver |

Pluggable binary normalizer

from betterdb_agent_cache import compose_normalizer, hash_base64

normalizer = compose_normalizer({"base64": hash_base64})

Observability

  • OpenTelemetry spans on every cache operation
  • Prometheus counters, histograms, and gauges (requests_total, operation_duration_seconds,
    cost_saved_total, stored_bytes_total, active_sessions)

Quick start

import asyncio
import valkey.asyncio as valkey_client
from betterdb_agent_cache import AgentCache, ModelCost, TierDefaults
from betterdb_agent_cache.adapters.openai import prepare_params
from betterdb_agent_cache.types import AgentCacheOptions

client = valkey_client.Valkey(host="localhost", port=6379)
cache = AgentCache(AgentCacheOptions(
    client=client,
    tier_defaults={"llm": TierDefaults(ttl=3600)},
    cost_table={"gpt-4o-mini": ModelCost(input_per_1k=0.00015, output_per_1k=0.0006)},
))

async def main():
    params = await prepare_params({
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": "What is 2+2?"}],
    })

    result = await cache.llm.check(params)
    if result.hit:
        print("Cache hit:", result.response)
    else:
        # ... call OpenAI ...
        await cache.llm.store(params, "Four")

asyncio.run(main())

Full changelog

See CHANGELOG.md for detailed history.

agent-cache-v0.4.0 New feature
Notable features
  • Bundled default cost table sourced from LiteLLM's `model_prices_and_context_window.json`
  • Cost tracking works out of the box for over 100 models without manual configuration
  • useDefaultCostTable option (default true) to enable/disable the bundled table and merge user‑supplied entries
Full changelog

Added

  • Bundled default cost table
    • Cost tracking works out of the box for 100+ models including GPT-4o, Claude, and Gemini — no costTable configuration required
    • User-supplied costTable entries are merged on top of the defaults, allowing selective overrides without losing coverage for other models
  • New useDefaultCostTable option on AgentCacheOptions
    • Defaults to true. Set to false to disable the bundled table entirely and supply your own
  • DEFAULT_COST_TABLE export
    • The bundled table is now exported from the main entry point for inspection or extension
  • update:pricing npm script
    • Regenerates defaultCostTable.ts from the latest LiteLLM pricing data

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.15.0...agent-cache-v0.4.0

v0.15.0 Breaking risk
Notable features
  • Vector/AI tab automatically appears when valkey-search or RediSearch is detected, showing FT.SEARCH ops/sec, latency charts, date range picker, and live updates.
  • Prometheus gauges for vector index docs, memory, failures, percent indexed, commandstats calls total, and latency are exposed on instances with a Search module.
Full changelog

Vector / AI tab

A new Vector / AI tab joins the monitor sidebar when BetterDB detects valkey-search or RediSearch on a connection. No configuration required - the tab appears automatically based on capability detection and stays hidden when the module is not loaded.

The tab surfaces two things that weren't previously visible:

FT.SEARCH workload over time. The monitor now tracks search query volume and latency as a continuous time-series, persisted to storage on each poll cycle. The tab shows an ops/sec chart and an average latency chart, defaulting to the last hour and live-updating every 15 seconds. A date range picker lets you query any historical window, pausing live polling while a custom range is active.

Vector index health. Every index on the instance is listed with its doc count, record count, deleted doc count, indexing failure count, and current indexing state. Rows with failures are highlighted. Three health alerts surface as banners when conditions warrant:

  • Indexing failures detected on any index
  • An index is actively backfilling
  • Deleted documents are accumulating

Both Valkey with valkey-search and Redis with RediSearch are supported.

Prometheus metrics

Six new gauges are exposed via /prometheus/metrics on instances where a Search module is detected:

```
betterdb_vector_index_docs{connection, index}
betterdb_vector_index_memory_bytes{connection, index}
betterdb_vector_index_indexing_failures{connection, index}
betterdb_vector_index_percent_indexed{connection, index}

betterdb_commandstats_calls_total{connection, command}
betterdb_commandstats_latency_us{connection, command}
```

Stale labels are removed automatically when an index is dropped or a command disappears from INFO commandstats.

FT.* fixes in the commandlog

FT.SEARCH commands carry vector embeddings as binary PARAMS blocks. These were previously stored and displayed as raw bytes in the commandlog, making search commands unreadable and impossible to group by pattern. Binary and oversized arguments are now replaced with <blob>. FT.* commands are also excluded from the byKeyPrefix aggregation, which was producing meaningless patterns like idx_cache: by splitting index
names on :.

Bug fixes

  • Dark mode: white code blocks now render with dark text. Code blocks and <pre> elements in the Settings page (MCP token display, Claude Code config snippet) and the Webhook Deliveries panel were using bg-white without a corresponding dark text override, making them unreadable in dark mode. Fixed with dark:text-gray-900. (#119)
  • API: 404 returned when no connection can be resolved, rather than an empty array. Affects the commandstats history and summary endpoints when no x-connection-id header is sent and no default connection is configured.

Internal

  • License key included in telemetry ping events.

What's Changed

  • Feature/agent cache adding OpenAI anthropic llamaindex adapters by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/115
  • Feature/agent cache adding OpenAI anthropic llamaindex adapters by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/116
  • feature: slowlog FT.* fix, vector index health metrics, commandstats time-series by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/111
  • feature: Vector / AI monitor tab (frontend) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/112
  • added license key to telemetry_ping events. Refactored util method location by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/118
  • feature: close commandstats AC gaps (snapshot endpoint, absolute totals, 60s) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/113
  • feature: commandstats API endpoints + Prometheus gauges per spec by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/114
  • Agent cache py by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/117

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.14.2...v0.15.0

agent-cache-v0.3.0 New feature
Notable features
  • Four new sub-path imports for OpenAI, Anthropic, and LlamaIndex provider adapters
  • Pluggable `BinaryNormalizer` interface with built‑in helpers (hashBase64, hashUrl, fetchAndHash, etc.)
  • Extended `LlmCacheParams` now includes toolChoice, seed, stop, responseFormat, reasoningEffort, and promptCacheKey
Full changelog

Multi-modal support and full provider adapter coverage for OpenAI, Anthropic, and LlamaIndex.


What's new

New provider adapters

Four new sub-path imports covering every major provider:

| Import | Provider |
|---|---|
| @betterdb/agent-cache/openai | OpenAI Chat Completions |
| @betterdb/agent-cache/openai-responses | OpenAI Responses API |
| @betterdb/agent-cache/anthropic | Anthropic Messages |
| @betterdb/agent-cache/llamaindex | LlamaIndex |

Each adapter converts provider-native request params into the canonical LlmCacheParams format — no manual normalisation required.

OpenAI Chat handles text, images (URL + base64), audio, files, tool calls, and legacy function role messages.

OpenAI Responses additionally covers reasoning items, function_call / function_call_output item types, and instructions promoted to a system message.

Anthropic covers tool use blocks, tool result blocks, and thinking / extended thinking blocks alongside standard image sources.

LlamaIndex wraps ChatMessage history including text and image nodes.


Pluggable binary normalizer

Binary content (images, audio, documents) is now a first-class part of the cache key pipeline. The new BinaryNormalizer interface lets you control how blobs are reduced to a stable string before hashing.

import { composeNormalizer } from '@betterdb/agent-cache';

const normalizer = composeNormalizer({
  // Hash base64 payloads by their decoded bytes
  base64: (data) => hashBase64(data),
  // Fetch remote images and hash the response body
  url: (url) => fetchAndHash(url),
  // Use OpenAI file IDs directly as cache keys
  fileId: (id, provider) => `${provider}:${id}`,
});

Built-in helpers:

| Helper | Behaviour |
|---|---|
| hashBase64(data) | SHA-256 of decoded bytes |
| hashBytes(data) | SHA-256 of raw bytes |
| hashUrl(url) | Normalised URL (sorted query params, lowercased host) |
| fetchAndHash(url) | Fetches URL and SHA-256s the body |
| passthrough(ref) | Scheme-prefixed ref, no transformation |
| composeNormalizer(cfg) | Build a normalizer from per-source / per-kind handlers |

The defaultNormalizer uses passthrough — zero-latency, no network calls, suitable for most use cases.


Extended cache key coverage

LlmCacheParams now includes all parameters that affect model output:

  • toolChoice, seed, stop, responseFormat
  • reasoningEffort — for extended thinking models
  • promptCacheKey — pass-through for provider-level prompt caching

New examples

Runnable examples added for all three new providers:

examples/openai/
examples/anthropic/
examples/llamaindex/

Bug fixes

  • Null tool output (openai-responses): function_call_output items with null or undefined output now produce an empty string instead of the two-character literal "", which was corrupting cache key hashes.

Installation

npm install @betterdb/[email protected]

Full changelog

See CHANGELOG.md for a complete list of changes.

What's Changed

  • Feature/agent cache adding OpenAI anthropic llamaindex adapters by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/115
  • Feature/agent cache adding OpenAI anthropic llamaindex adapters by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/116

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.14.2...agent-cache-v0.3.0

v0.14.2 Security relevant
Security fixes
  • CVE-2026-33806 — vulnerability in Fastify (GHSA-247c-9743-5963)
  • dep: CVE-2026-6410 — static file serving issue (GHSA-pr96-94w5-mx2h)
  • dep: CVE-2026-6414 — static file serving issue (GHSA-x428-ghpx-8j92)
Notable features
  • @betterdb/agent-cache package added — multi‑tier LLM/tool/session cache
  • Cluster support for agent-cache
Full changelog

Security updates

fastify 5.8.4 → 5.8.5

Fixes CVE-2026-33806 — a security vulnerability in the Fastify HTTP framework. See GHSA-247c-9743-5963.

@fastify/static 9.0.0 → 9.1.1

Fixes two CVEs in static file serving:

vite 8.0.2 → 8.0.5

Multiple path traversal and filesystem boundary bypass fixes in the dev server:

  • server.fs checks now apply to env transport requests and query-stripped paths
  • Sourcemap handlers no longer allow referencing files outside the package root

Bug fixes

Vector Search

  • Fixed crashes caused by out-of-bounds data
  • Fixed Find Similar button being difficult to click
  • Fixed graph labels being unreadable and not respecting the active color scheme

What's Changed

  • added licenseKey to posthog events by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/104
  • Add @betterdb/agent-cache package — multi-tier LLM/tool/session cache with framework adapters by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/105
  • cluster support for agent-cache by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/108
  • build(deps-dev): bump vite from 8.0.2 to 8.0.5 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/99
  • build(deps): bump @nestjs/core from 11.1.17 to 11.1.18 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/100
  • build(deps): bump fastify from 5.8.4 to 5.8.5 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/106
  • build(deps): bump @fastify/static from 9.0.0 to 9.1.1 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/110

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.14.1...v0.14.2

agent-cache-v0.2.0 Breaking risk
⚠ Upgrade required
  • Update dashboards or alerts that reference the cache.touched_count OTel span attribute to use cache.touched_count_approx.
  • When running in cluster mode, set VALKEY_CLUSTER=1 (or override with VALKEY_CLUSTER_NODES) to configure framework examples against a Valkey cluster.
Breaking changes
  • Renamed agent_cache.session.touch OTel span attribute from cache.touched_count to cache.touched_count_approx; value now counts keys sent to EXPIRE rather than successfully refreshed.
Notable features
  • Added full cluster mode support for SCAN-based operations and bulk commands (DEL, MGET) using pipelined individual commands.
  • Framework examples (LangChain, LangGraph, Vercel AI SDK) now honor VALKEY_CLUSTER=1 env var to run against a Valkey cluster without code changes.
Full changelog

Cluster mode support

All SCAN-based operations now work correctly when an iovalkey Cluster client is passed. No API changes required - swap a standalone Valkey instance for a Cluster instance and everything works.

Affected methods: flush(), destroyThread(), invalidateByModel(), invalidateByTool(), getAll(), touch(), scanFieldsByPrefix()

import { Cluster } from 'iovalkey';

const client = new Cluster([
  { host: 'localhost', port: 6401 },
  { host: 'localhost', port: 6402 },
  { host: 'localhost', port: 6403 },
]);

const cache = new AgentCache({ client: client as any, ... });

CROSSSLOT fix

Multi-key DEL and MGET commands cause CROSSSLOT errors in cluster mode when keys span different hash slots on the same node. All bulk operations now use pipelines of individual commands instead.

Framework examples

The LangChain, LangGraph, and Vercel AI SDK examples support a VALKEY_CLUSTER=1 environment variable to run against a cluster without code changes:

VALKEY_CLUSTER=1 npx tsx index.ts
Cluster mode - nodes: localhost:6401, localhost:6402, localhost:6403

VALKEY_CLUSTER_NODES overrides the default node list.

Breaking changes

  • The agent_cache.session.touch OTel span attribute is renamed from cache.touched_count to cache.touched_count_approx. The value counts keys sent to EXPIRE, not keys that successfully refreshed. Update any dashboards or alerts keyed on
    cache.touched_count.

Infrastructure

  • docker-compose.test.yml gains a 3-node cluster on ports 6401–6403 with an init container that forms the cluster automatically
  • global-setup.ts starts the cluster containers and waits for cluster_state:ok before running tests
  • New integration test suite (AgentCache.cluster.integration.test.ts) covering all cluster operations - skips gracefully when the cluster is unavailable

What's Changed

  • cluster support for agent-cache by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/108

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/agent-cache-v0.1.0...agent-cache-v0.2.0

agent-cache-v0.1.0 New feature
Notable features
  • Three cache tiers: LLM response (exact‑match with deterministic hashing), Tool result (per‑tool TTL policies and selective invalidation), Session state (sliding‑window TTL, LangGraph checkpoint support)
  • Framework adapters for LangChain, Vercel AI SDK, and LangGraph
  • Built‑in OpenTelemetry tracing and Prometheus metrics
Full changelog

Multi-tier exact-match cache for AI agent workloads backed by Valkey. Three cache tiers behind one connection: LLM responses, tool results, and session state. Built-in OpenTelemetry tracing and Prometheus metrics. No modules required - works on vanilla Valkey 7+, ElastiCache, Memorystore, MemoryDB, and any Redis 6.2+ endpoint.

Install

npm install @betterdb/agent-cache iovalkey

What's in this release

Three cache tiers

  • LLM response cache - exact match on model, messages, temperature, top_p, max_tokens, and tools. Canonical JSON serialization with sorted keys for deterministic hashing. Tool arrays sorted by function name for order-independent matching.
  • Tool result cache - cache by tool name and argument hash. Per-tool TTL policies persisted to Valkey. Invalidate by tool, by specific arguments, or by model.
  • Session state - key-value storage with sliding window TTL. Individual field expiry (not Redis HASH). LangGraph checkpoint support on vanilla Valkey without RedisJSON or RediSearch.

Framework adapters

Three optional subpath exports. Only install the peer dependency you use.

  • LangChain (@betterdb/agent-cache/langchain) - BetterDBLlmCache implementing BaseCache. Plugs into ChatOpenAI's cache option. Auto-extracts token counts from usage_metadata for cost tracking.
  • Vercel AI SDK (@betterdb/agent-cache/ai) - createAgentCacheMiddleware() implementing LanguageModelMiddleware. Intercepts non-streaming doGenerate calls. Cache hits include providerMetadata: { agentCache: { hit: true } }.
  • LangGraph (@betterdb/agent-cache/langgraph) - BetterDBSaver implementing BaseCheckpointSaver. Full checkpoint protocol including pendingWrites reconstruction, interrupt/resume, and human-in-the-loop patterns. Works on vanilla Valkey 7+ without Redis 8, RedisJSON, or RediSearch.

Observability

  • OpenTelemetry - every public method emits a span with attributes for cache key, tier, hit/miss, model, tool name, TTL, and byte size.
  • Prometheus via prom-client - requests_total, operation_duration_seconds, cost_saved_total, stored_bytes_total, active_sessions. Configurable metric prefix and registry.

Stats and self-optimization

  • stats() returns per-tier hit/miss counts, hit rates, session read/write counts, aggregate cost savings in microdollars, and per-tool breakdowns.
  • toolEffectiveness() ranks cached tools by hit rate and recommends TTL adjustments: increase_ttl (>80% hit rate, TTL <1hr), optimal (40-80%), or decrease_ttl_or_disable (<40%).
  • Cost tracking via costTable config - provide model pricing, and cache hits automatically accumulate savings.

Error handling

  • AgentCacheError base class, AgentCacheUsageError for caller mistakes (colons in tool names, glob chars in thread IDs), ValkeyCommandError for Valkey failures with cause chaining.
  • Corrupt JSON entries are self-healing - deleted on first detection and treated as misses.
  • Tool name validation rejects colons (used as key delimiters) at call time rather than producing silent key collisions.

Known limitations

  • Streaming - not cached by the Vercel AI SDK adapter (only doGenerate, not doStream). LangChain .stream() bypasses the cache (LangChain architecture limitation). Accumulate the full response before caching when using the direct API.
  • Cluster mode - SCAN-based operations (destroyThread, invalidateByTool, invalidateByModel, flush) only iterate the node they're sent to. In multi-node clusters these may silently leave keys on other nodes. Use the iovalkey cluster client's per-node scan for full coverage. Cluster mode support is planned.
  • LangGraph list() - loads all checkpoint data for a thread into memory before filtering. The limit: 1 fast path reads checkpoint:latest directly. For threads with thousands of large checkpoints, consider langgraph-checkpoint-redis with Redis 8+.
  • Active sessions gauge - approximate, tracked via in-memory LRU (bounded at 10k). Does not survive process restarts.

Links

What's Changed

  • added licenseKey to posthog events by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/104
  • Add @betterdb/agent-cache package — multi-tier LLM/tool/session cache with framework adapters by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/105

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.14.1...agent-cache-v0.1.0

v0.14.1 Maintenance

Routine maintenance release for BetterDB-inc/monitor.

Changelog

Url updates

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.14.0...v0.14.1

v0.14.0 Breaking risk
⚠ Upgrade required
  • CLI defaults to read‑only; enable writes by setting BETTERDB_UNSAFE_CLI=true at deploy time.
  • Cloud deployments must allow /cli/ws through auth middleware (already whitelisted).
  • To use the registration flow, configure VITE_REGISTRATION_URL and ENTITLEMENT_URL and ensure the entitlement service has a RESEND_API_KEY.
Notable features
  • Integrated browser CLI panel (WebSocket‑backed, read‑only default, optional unsafe write mode via BETTERDB_UNSAFE_CLI)
  • Free registration and license activation flow with new Settings → License UI and POST /license/activate API
  • Responsive layout refactor extracting App.tsx into modular components and shadcn primitives
Full changelog

Highlights: an integrated browser CLI for running Valkey/Redis commands directly from the Monitor UI, a free registration + license activation flow, and a refactored responsive
layout.

Features

Integrated CLI panel (#96)

Run Valkey/Redis commands without leaving the browser. A new collapsible bottom panel exposes a WebSocket-backed terminal with command history and keyboard shortcuts.

  • Two modes:
    • Safe (default) — read-only allowlist, 18 destructive commands blocked, bare-subcommand bypass closed (e.g. CONFIG without a subcommand is rejected), SENTINEL and SLOWLOG RESET
      removed from the allowlist.
    • Unsafe — opt in with BETTERDB_UNSAFE_CLI=true to allow writes; surfaces a startup warning and an unsafeCliEnabled flag in the health response.
  • Backend (apps/api/src/cli/): new CliGateway WebSocket endpoint at /cli/ws with per-connection token-bucket rate limiting (50 cmd/s), 30s command timeout, 512 KB response
    truncation, 1 MiB payload limit, and JWT session-cookie validation in cloud mode. Each WS connection gets a dedicated BetterDB-CLI Valkey client via a new DatabasePort.call(..., { cli })
    adapter API.
  • Frontend: collapsible CliPanel with Ctrl+` shortcut, ref-based history navigation (no re-render cascade), sessionStorage persistence, and an auto-reconnecting WebSocket hook
    with exponential backoff. Built-in commands: help, clear, history, exit.
  • Shared: command parser and checkSafeMode / checkBlocked filters centralized in @betterdb/shared so backend and frontend agree on policy.
  • 44 backend tests + 13 frontend tests.

Closes #91, #92, #93, #94.

Free registration & license activation flow (#98)

End-to-end self-serve onboarding from email to active Enterprise license.

  • Web: new Settings → License section. Users register an email (via VITE_REGISTRATION_URL) and activate the returned key in-app.
  • API: new POST /license/activate endpoint, persists activated keys to disk, hardened error handling and message extraction.
  • Entitlement service: new /v1/registrations endpoint creates or resends Enterprise licenses and delivers them via Resend; cloud entitlement resolution now keys off tenantId; CORS and
    env wiring updated.
  • New env vars: VITE_REGISTRATION_URL, ENTITLEMENT_URL.

Responsive layout refactor (#103)

App.tsx slimmed down to providers and bootstrap; layout extracted into a dedicated module.

  • New components in src/components/layout/: AppLayout, AppSidebar, NavItem, CommunityBanner, FeedbackModal.
  • New shadcn primitives: Sidebar, Sheet, Input, plus a useIsMobile hook.
  • Responsive collapsible sidebar with persisted open/closed state; CliPanel repositioned to follow the sidebar via peer-data-[state].
  • Print styles updated to hide the new sidebar.

Bumps

  • @betterdb/agent 1.3.0 → 1.4.0 (#101)
  • App workspaces (api, web, cli, shared, root) → 0.14.0

Notes for upgraders

  • The integrated CLI is read-only by default. Set BETTERDB_UNSAFE_CLI=true to allow writes; this is intentionally a deploy-time decision, not a UI toggle.
  • Cloud-mode deployments must permit /cli/ws through the auth middleware (already whitelisted in this release).
  • If you use the new registration flow, configure VITE_REGISTRATION_URL and ENTITLEMENT_URL and ensure the entitlement service has a RESEND_API_KEY (or watch its console for keys in
    dev).

What's Changed

  • feature: integrated CLI panel (#91) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/96
  • Bump version from 1.3.0 to 1.4.0 by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/101
  • Registration flow by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/98
  • Refactor App.tsx into modular layout components by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/103

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.13.5...v0.14.0

agent-v1.4.0 Feature
Notable features
  • CLI support for executing commands in safe and unsafe modes using user‑provided flags
Changelog

Added CLI support for command execution in safe and unsafe mode depending on user provided flags

v0.13.5 Bugfix

Bug fixes and stability improvements in BetterDB-inc/monitor.

Full changelog

Fixed build flow

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.13.1...v0.13.5

v0.13.1 Bugfix

Bug fixes and stability improvements in BetterDB-inc/monitor.

Full changelog

Fixed build flow

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.13.0...v0.13.1

v0.13.0 New feature
Notable features
  • TelemetryPort interface with NoopAdapter and factory for provider decoupling
  • Web frontend migration to shadcn component library
Full changelog

Features

  • Telemetry adapter abstraction — Introduced TelemetryPort interface with NoopAdapter and a factory, decoupling telemetry from concrete providers (#77)
  • shadcn UI migration — Migrated the web frontend to the shadcn component library (#82)

Fixes

  • Fix banner coloring for themes (#95)

What's Changed

  • shadcn to a working point by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/82
  • feature: telemetry adapter abstraction (TelemetryPort + NoopAdapter + factory) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/77
  • fix banner coloring for themes by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/95

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.12.1...v0.13.0

v0.12.1 Breaking
Breaking changes
  • Migration flow options were swapped, altering required configuration.
Full changelog

Swapped options for the migration flow

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.12.0...v0.12.1

mcp-v1.1.0 Security relevant
Security fixes
  • Pin axios to 1.14.0 to prevent compromised version 1.14.1
  • Override rollup, minimatch, and flatted packages to resolve CVEs
Notable features
  • Throughput forecasting UI and API
Full changelog

Security and telemetry improvements

What's Changed

  • fix(proprietary): rename license module dir to licenses for macOS by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/58
  • build(deps): bump @nestjs/platform-fastify from 11.1.14 to 11.1.16 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/52
  • chore: gradual dependency upgrade (P0–P5) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/59
  • mcp-logging by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/60
  • fix(security): pin axios to 1.14.0 to prevent compromised 1.14.1 by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/64
  • fix(security): override rollup, minimatch, and flatted to resolve CVE… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/65
  • Add automated PR review via Claude Code GitHub Action by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/66
  • Claude review o auth by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/67
  • Claude review o auth by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/68
  • Throughput forecasting UI and API by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/69
  • Feature migration by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/62

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/semantic-cache-v0.1.0...mcp-v1.1.0

v0.12.0 Security relevant
⚠ Upgrade required
  • Major version upgrades across the monorepo (Prisma 5→7, Stripe 14→20, Jest 29→Vitest 4, Vite 6→8, React 18→19 types, Tailwind CSS 3→4, NestJS CLI 10→11, ESLint to flat config)
  • Add semantic-cache package for Valkey‑native LLM caching with observability
  • Automated PR review via Claude Code GitHub Action (triggered by `@claude` mentions)
Security fixes
  • axios pinned to 1.14.0 — prevents resolution of compromised version 1.14.1 containing a hidden RAT (pinned via `pnpm.overrides`)
  • Transitive dependency overrides: rollup >=4.59.0, minimatch >=3.1.4, flatted >=3.4.2 to resolve Dependabot CVE alerts
Notable features
  • Guided three‑phase Redis ↔ Valkey migration workflow with analysis, execution (RedisShake or command‑based), and post‑migration validation
  • Metric forecasting page and API with configurable rolling windows, ceilings, and alert thresholds
Full changelog

Database Migration

A new guided workflow for migrating data between Redis and Valkey instances, built into the BetterDB monitor across three phases.

Pre-migration analysis

Connect a source and target instance and get a compatibility report before moving any data. The analysis samples up to 50K keys per node and produces:

  • Data type breakdown with estimated memory per type
  • TTL distribution (no expiry, <1h, <24h, <7d, >7d)
  • Hash Field Expiry (HFE) detection for Valkey 8.1+ sources
  • Top command patterns from COMMANDLOG/SLOWLOG
  • 10 compatibility checks that flag blocking issues (Valkey→Redis direction, unsupported HFE, missing modules, cluster/standalone mismatch, multi-DB to cluster, ACL differences, eviction policy and persistence mismatches)

Reports are exportable as JSON. Full cluster support - analysis connects to each master node individually.

Execution

Two migration modes:

  • RedisShake - spawns the RedisShake binary for fast DUMP/RESTORE transfers
  • Command-based - in-process migration using native read/write commands, works across versions with no external dependencies

Real-time progress tracking, live log viewer, and safe cancellation. Compound types are written to a temporary same-slot key and atomically renamed so readers never see partial data. Credentials are automatically redacted from all logs.

Post-migration validation (Pro)

Verifies migration success by comparing key counts (flags >1% discrepancy), spot-checking 500 random keys with binary-safe value comparison, and comparing target metrics against the source's pre-migration baseline.


Metric Forecasting

New forecasting page and API for tracking metric trends over time. Configurable rolling window, ceiling values, and alert thresholds per metric. Includes a settings panel and chart visualization.


Automated PR Review

Added a Claude Code GitHub Action for automated PR reviews. Claude posts inline comments on PRs and can be triggered via @claude mentions.


Security Fixes

  • axios pinned to 1.14.0 - version 1.14.1 was published via a hijacked maintainer account containing a hidden RAT. Pinned via pnpm.overrides to prevent resolution to the compromised version.
  • Transitive CVE overrides - forced rollup >=4.59.0, minimatch >=3.1.4, and flatted >=3.4.2 to resolve Dependabot alerts that couldn't be auto-fixed.

Dependency Upgrades

Major version upgrades across the monorepo:

  • Prisma 5 → 7 (driver adapters, new config format)
  • Stripe 14 → 20
  • Jest 29 → Vitest 4
  • Vite 6 → 8 (Rolldown)
  • React 18 → 19 types
  • Tailwind CSS 3 → 4 (CSS-first config)
  • NestJS CLI 10 → 11
  • ESLint migrated to flat config

What's Changed

  • Add semantic-cache package: Valkey-native LLM cache with observability by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/55
  • fix(proprietary): rename license module dir to licenses for macOS by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/58
  • build(deps): bump @nestjs/platform-fastify from 11.1.14 to 11.1.16 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/52
  • chore: gradual dependency upgrade (P0–P5) by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/59
  • mcp-logging by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/60
  • fix(security): pin axios to 1.14.0 to prevent compromised 1.14.1 by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/64
  • fix(security): override rollup, minimatch, and flatted to resolve CVE… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/65
  • Add automated PR review via Claude Code GitHub Action by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/66
  • Claude review o auth by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/67
  • Claude review o auth by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/68
  • Throughput forecasting UI and API by @jamby77 in https://github.com/BetterDB-inc/monitor/pull/69
  • Feature migration by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/62

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.11.1...v0.12.0

semantic-cache-v0.1.0 New feature
⚠ Upgrade required
  • Requires Node.js 20+
  • Valkey must include valkey-search module (use `valkey/valkey-bundle:unstable` with current tag)
  • Peer dependency `iovalkey >= 0.3.0` required
Notable features
  • SemanticCache class with KNN similarity lookup, storage, invalidation, stats and indexInfo
  • OpenTelemetry spans for every operation with detailed attributes
  • Prometheus metrics: requests_total, similarity_score, operation_duration_seconds, embedding_duration_seconds
Full changelog

First release. Valkey-native semantic cache for LLM applications with built-in OpenTelemetry and Prometheus instrumentation.

What's included

Core cache

  • SemanticCache class — framework-agnostic, backed by Valkey Search (valkey-search module required)
  • check(prompt, options?) — KNN vector similarity lookup returning hit/miss with similarity score, confidence level (high | uncertain | miss), and nearest-miss diagnostics
  • store(prompt, response, options?) — stores prompt/response pairs with optional TTL, category tag, and model tag
  • invalidate(filter) — batch delete by valkey-search filter expression (e.g. @model:{gpt-4o}); returns deleted count and truncation flag
  • stats() — hit/miss/total counts and hit rate, persisted in Valkey
  • indexInfo() — index metadata from FT.INFO
  • flush() — drops the FT index and cleans up all entry keys

Observability

  • OpenTelemetry spans on every operation with cache.hit, cache.similarity, cache.threshold, cache.confidence, and cache.category attributes
  • Four Prometheus metrics: {prefix}_requests_total, {prefix}_similarity_score, {prefix}_operation_duration_seconds, {prefix}_embedding_duration_seconds
  • Custom prom-client Registry support for library/multi-tenant contexts

Framework adapters

  • @betterdb/semantic-cache/langchainBetterDBSemanticCache extending LangChain BaseCache, with optional filterByModel scoping
  • @betterdb/semantic-cache/aicreateSemanticCacheMiddleware for Vercel AI SDK (wrapLanguageModel)

Configuration

  • Per-category threshold overrides via categoryThresholds
  • Uncertainty band: hits within uncertaintyBand of the threshold are returned with confidence: 'uncertain'
  • Sliding TTL refresh on cache hits

Valkey Search 1.2 compatibility

Verified against valkey-search module v66048. Four divergences from Redis/RediSearch handled:

  1. FT.INFO error message format differs — all three known patterns matched for cross-compatibility
  2. FT.DROPINDEX DD (Delete Documents flag) not supported — key cleanup done via SCAN + DEL
  3. KNN score aliases cannot be used in RETURN or SORTBY — results returned without RETURN clause, pre-sorted by distance
  4. Vector field dimension nested inside "index" sub-array as "dimensions" rather than top-level DIM key

Requirements

  • Node.js 20+
  • Valkey with valkey-search module (use valkey/valkey-bundle:unstable — current tag shipping valkey-search 1.2)
  • iovalkey >= 0.3.0 (peer dependency)

Install

npm install @betterdb/semantic-cache

LangChain and Vercel AI SDK adapters are optional peer dependencies — install only what you need.

What's Changed

  • Add semantic-cache package: Valkey-native LLM cache with observability by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/55

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/mcp-v1.0.0...semantic-cache-v0.1.0

mcp-v1.0.0 New feature
⚠ Upgrade required
  • Requires @betterdb/monitor npm package version 0.11.1 or newer for new API support.
  • Persistent monitor writes a PID file at `~/.betterdb/monitor.pid`; ensure the directory is writable.
Notable features
  • Zero‑config local setup via `--autostart` with ephemeral and persistent modes (flags: `--port`, `--storage sqlite|memory`, `--stop`).
  • Connection management tools: `test_connection`, `add_connection`, `remove_connection`, `set_default_connection`.
  • Monitor lifecycle tools: `start_monitor` to launch/reattach, `stop_monitor` to cleanly shut down.
Full changelog

What's new

Zero-config local setup with --autostart

The MCP server can now start and manage a local BetterDB monitor automatically - no separate terminal, no manual setup required.

Ephemeral (monitor dies when the MCP session ends):

"args": ["@betterdb/mcp", "--autostart"]

Persistent (monitor survives across sessions):

"args": ["@betterdb/mcp", "--autostart", "--persist"]

Additional flags:

  • --port <number> - port for the local monitor (default 3001)
  • --storage sqlite|memory - storage backend (default sqlite, data at ~/.betterdb/data/)
  • --stop - stop a persisted monitor and clean up

On persistent mode, the monitor process is tracked via ~/.betterdb/monitor.pid. Subsequent MCP sessions reattach to the running monitor automatically rather than spawning a new one.

Connection management tools

Four new tools for managing Valkey/Redis connections directly from your AI assistant - no UI required:

  • test_connection - validate credentials before saving
  • add_connection - register a new connection, optionally set as default
  • remove_connection - remove a connection by ID
  • set_default_connection - change the active default connection

Monitor lifecycle tools

Two new tools to control a persistent monitor from within an MCP session:

  • start_monitor - start a persistent monitor (or reattach if already running)
  • stop_monitor - stop a persistent monitor and clean up

A lot of this release depends on https://www.npmjs.com/package/@betterdb/monitor 0.11.1+ as it introduces some of the API to be used with the MCP - autostart and connections management

What's Changed

  • Add MCP autostart/stop lifecycle, connection management tools, and en… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/54

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.11.0...mcp-v1.0.0

v0.11.1 New feature
Notable features
  • Environment variable overrides (`DB_HOST`, `DB_PORT`, `DB_USERNAME`, `DB_PASSWORD`, `DB_TYPE`, `STORAGE_TYPE`, `STORAGE_SQLITE_FILEPATH`, `STORAGE_URL`, `PORT`, `BETTERDB_LICENSE_KEY`) take precedence over saved config when the monitor is spawned programmatically.
Full changelog

What's new

Environment variable overrides for all connection settings

Environment variables now take precedence over saved config when the monitor is spawned programmatically (e.g. via --autostart). This enables the MCP to configure the monitor at spawn time without modifying ~/.betterdb/config.json.

Overridable via env: DB_HOST, DB_PORT, DB_USERNAME, DB_PASSWORD, DB_TYPE, STORAGE_TYPE, STORAGE_SQLITE_FILEPATH, STORAGE_URL, PORT, BETTERDB_LICENSE_KEY.

Saved config remains the fallback when no env override is present - existing setups are unaffected.

What's Changed

  • Add MCP autostart/stop lifecycle, connection management tools, and en… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/54

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.11.0...v0.11.1

v0.11.0 New feature
Notable features
  • Unified multi‑lane event timeline displaying anomalies, COMMANDLOG entries, latency events, CPU/IO usage on a shared time axis
  • Interactive clicking of time buckets to view correlated signals across all views
Full changelog

Unified event timeline

The dashboard now includes a multi-lane event timeline that puts all operational signals on a shared time axis: anomalies, COMMANDLOG entries, latency events, and CPU/IO usage side by side.

Click any time bucket to see what correlated across all signals at that moment. Drag to select a range and open it directly in the slow log, anomaly, latency, or client analytics views.

The goal is postmortem clarity — correlating signals that used to require jumping between pages.

Bug fixes

  • Fixed anomaly event markers not being clickable in certain zoom levels
  • Fixed bucket detail panel not clearing on connection switch

What's Changed

  • Add unified Event Timeline with multi-lane visualization and date ran… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/53

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.10.0...v0.11.0

agent-v1.3.0 New feature
⚠ Upgrade required
  • Requires @betterdb/shared v0.10.0; update agent to v1.3.0 and restart to enable new vector search features in the monitoring UI.
Notable features
  • Full set of vector search exploration commands (FT.SEARCH, FT.TAGVALS, FT.CONFIG GET, FT.PROFILE) now supported on agent connections
  • Text search with pagination, DIALECT 2 support for Redis, and input validation (query length cap, offset/limit clamping)
  • Tag value listing via FT.TAGVALS with fallback to sampling when unavailable
Full changelog

New Features

Vector Search Commands

Agent connections now support the full set of vector search exploration commands, matching the capabilities already available on direct connections.

  • Text search (FT.SEARCH) — Full-text queries with pagination, DIALECT 2 support for Redis, and input validation (query length cap, offset/limit clamping).
  • Tag value listing (FT.TAGVALS) — Retrieves distinct tag values for a field, with automatic fallback to FT.SEARCH * sampling when FT.TAGVALS is not available.
  • Search config (FT.CONFIG GET) — Fetches search module configuration. Returns an empty result gracefully when the command is unavailable (e.g., Valkey Search).
  • Query profiling (FT.PROFILE) — Profiles search queries with optional LIMITED mode. Returns a structured breakdown of parsing time, iterator profiles, and result processor stages.

Bug Fixes

  • Text search input validation — Query length, offset, and limit are now validated and clamped before being sent to the server, matching the unified adapter's behavior.
  • Profile search query validation — Added query length and emptiness checks to prevent unbounded strings from being forwarded.
  • FT.PROFILE argument order — The LIMITED flag is now correctly placed before QUERY, matching the documented command syntax.

Dependencies

  • Requires @betterdb/shared v0.10.0 (adds VectorIndexSnapshot and VectorIndexSnapshotQueryOptions types).

Upgrade Notes

This is a backwards-compatible release. Agents running v1.2.0 will continue to work but will not support text search, profiling, tag values, or config inspection through the monitoring UI. To enable these features, update and restart the agent.

v0.10.0 New feature
Notable features
  • Semantic cache detection with warnings for large caches lacking TTL policies
  • Index fragmentation alerts showing ratio and rebuild commands
  • FLAT-to-HNSW migration suggestions with FT.CREATE templates
Full changelog

Vector Search Explorer

What's new

Index Health Insights

  • Semantic cache detection — Indexes matching common semantic cache naming patterns are automatically classified and badged. If a semantic cache has over 1,000 documents and no apparent TTL policy, a warning surfaces with guidance on setting expiry to prevent unbounded memory growth.

  • Index fragmentation alerts — When the records-to-documents ratio exceeds 2x, a warning appears with the exact fragmentation ratio and a copy-paste FT.DROPINDEX + FT.CREATE command to rebuild the index.

  • FLAT-to-HNSW migration warnings — FLAT (brute-force) indexes with more than 10,000 documents trigger a suggestion to migrate to HNSW, including a ready-to-use FT.CREATE template with recommended M and EF_CONSTRUCTION parameters.

  • Memory footprint as % of instance RAM — Each index card and the overview grid now show index memory usage as a percentage of total instance memory (e.g., "42.3 MB (12.1% of instance)").

Historical Trending

  • Snapshot polling — A background poller captures document count and memory size for every vector index every 30 seconds, stored for up to 7 days. Old snapshots are pruned automatically.

  • Sparklines with trend indicators — Each index card shows a mini trend line of document count. An arrow and percentage label indicate whether the index is growing, shrinking, or stable.

  • Trend charts with time window selector — Click a sparkline to expand a full trend chart showing document count and memory over time. A segmented control switches between 6h, 24h, and 7d windows, with smart downsampling to ~200 points for smooth rendering regardless of window size.

Vector Similarity Graph

  • Canvas-based force-directed visualization — Renders vector relationships as an interactive graph using HTML5 Canvas and d3-force. Nodes represent documents, edges represent vector similarity.

  • Field-based coloring — Choose any non-vector field to color-code nodes by category, with an auto-generated legend.

  • Expand on click — Click any node to fetch its 10 nearest neighbors and add them to the graph, progressively exploring the vector space.

  • Pan, zoom, and drag — Scroll to zoom (0.1x–8x), drag the background to pan, drag nodes to reposition them. Camera state is preserved when expanding nodes.

Valkey Compatibility

  • Graceful feature detection — Features that depend on commands not available in Valkey Search (Text Search, Query Profiler, Config Inspector) are automatically hidden when connected to a Valkey instance.

  • SCAN-based fallbacks — Field distribution analysis falls back to SCAN + HGETALL sampling when FT.SEARCH * is not supported, so the Data tab works on both Redis and Valkey.

Transparency

  • Sample size callouts — The Data tab notes that statistics are computed from up to 100 sampled documents. The Graph tab shows how many documents are sampled out of the total index size.

What's Changed

  • Vector search improvements by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/51

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.9.1...v0.10.0

mcp-v0.1.4 Maintenance

Minor fixes and improvements.

Full changelog

Updated README and package.json

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/mcp-v0.1.3...mcp-v0.1.4

mcp-v0.1.3 Maintenance

Minor fixes and improvements.

Full changelog

Updated server name across the .json files

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/mcp-v0.1.1...mcp-v0.1.3

mcp-v0.1.2 Maintenance

Routine maintenance release for BetterDB-inc/monitor.

Full changelog

Added server.sjon

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.9.1...mcp-v0.1.2

mcp-v0.1.1 Maintenance

Minor fixes and improvements.

Full changelog

Added mcpName to the package.json

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.9.1...mcp-v0.1.1

v0.9.1 New feature
Security fixes
  • Sanitize FT.SEARCH filter input against injection (length limit, control characters, reject => operator)
  • Validate index names against /^[a-zA-Z_][a-zA-Z0-9_-]*$/ pattern to prevent invalid name usage
Notable features
  • Vector Search page with browse keys via SCAN + pipelined HGETALL and KNN similarity search by cosine/IP/L2 distance
  • Adaptive field layout grouping document fields by role with humanized labels, temporal deduplication, identifier dedup, and insight callouts
Full changelog

Vector Search

Introspect and explore your Valkey Search indexes directly from the monitor. The new Vector Search page provides two modes of interaction — browse keys by SCAN and
find similar vectors by cosine/IP/L2 distance.

Features:

  • Browse all keys belonging to a vector index using SCAN + pipelined HGETALL (compatible with Valkey Search v1.0.0)
  • Find similar vectors — select a source key and vector field to run a KNN similarity search
  • Adaptive field layout groups document fields by role (content, metric, temporal, provenance, identifier, payload) with distinct rendering per group
  • Field classification with humanized labels, temporal deduplication, and identifier dedup against the document key
  • Insight callouts with copy-to-clipboard for FT.CREATE command, index stats, and memory usage
  • Capability detection via FT._LIST — the page only appears when a Search module is detected

Bug Fixes:

  • Fix percentIndexed double-multiplication for Valkey Search instances that report backfill_complete_percent in 0–100 range
  • Fix binary args replacement loop corrupting the command name in agent executor
  • Add missing hasVectorSearch capability guard to vectorSearch() in the unified adapter
  • Add @IsNotEmpty() validation to sourceKey and vectorField in VectorSearchDto
  • Sanitize FT.SEARCH filter input against injection (length limit, control characters, => operator rejection)
  • Validate index names against /^[a-zA-Z_][a-zA-Z0-9_-]*$/ pattern

Agent Connection Stability

  • Fix: persistent data loss on agent reconnect — Agent connection IDs are now derived from the stable token ID (agent-{tokenId}) instead of a random UUID generated on
    each connection. This prevents historical data (hot keys, anomaly events, slowlog, command log) from being orphaned when an agent reconnects.

Other Fixes

  • Fix keyspace size calculation — wrap in Number() to prevent string concatenation from the INFO parser

What's Changed

  • Vector search by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/48
  • Mcp server by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/47
  • Mcp server by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/49
  • Mcp server by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/50

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.8.0...v0.9.1

mcp-v0.1.0 New feature
Notable features
  • 21 tools covering health checks, slowlog, COMMANDLOG (Valkey 8+), memory diagnostics, client activity, hot key detection, cluster-wide metrics, latency history, ACL audit, and anomaly detection
  • Works with any MCP client including Claude Code, Cursor, Windsurf, OpenAI Codex
  • Cloud and self‑hosted deployment with auto‑detected API prefix; no extra configuration required
Full changelog

First public release of the BetterDB MCP server — giving AI assistants like Claude Code and OpenAI Codex direct access to your Valkey and Redis observability data.

Highlights

  • 21 tools covering health checks, slowlog, COMMANDLOG (Valkey 8+), memory diagnostics, client activity, hot key detection, cluster-wide metrics, latency history, ACL audit, and anomaly detection
  • Works with any MCP client — Claude Code, Cursor, Windsurf, OpenAI Codex, and more
  • Cloud and self-hosted — auto-detects API prefix, no extra configuration needed
  • Secure — authenticates via BetterDB agent tokens (JWT); token optional for local development
  • Multi-instance support — list, select, and switch between instances; or pre-select via BETTERDB_INSTANCE_ID
  • Pro features surfaced gracefully — anomaly detection and other Pro-tier tools return clear upgrade prompts on community installs

Quick start

npx @betterdb/mcp

See the https://www.npmjs.com/package/@betterdb/mcp for full configuration instructions.

What's Changed

  • Mcp server by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/49

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/agent-v1.2.0...mcp-v0.1.0

agent-v1.2.0 New feature
Notable features
  • Support for Valkey Search / RediSearch commands over WebSocket enabling vector similarity search
  • Capability detection of FT module during handshake and reporting in capabilities array
  • Allowlist for FT._LIST, FT.INFO, and FT.SEARCH commands via subcommand routing
Full changelog

Vector Search Support

The agent now supports Valkey Search / RediSearch commands over the WebSocket protocol, enabling vector similarity search from remote-monitored instances.

Search module capability detection — During handshake, the agent probes for the Search module via FT._LIST. If available, FT is reported in the capabilities array,
allowing the monitor to show vector search features for agent-connected instances.

FT command allowlist — FT._LIST, FT.INFO, and FT.SEARCH are now permitted through the command executor via the existing subcommand routing system. FT commands are
dispatched using dot notation (FT.INFO, FT.SEARCH).

Binary protocol extension — Vector search requires transmitting binary embeddings (float arrays) that can't be represented as plain strings. The agent protocol now
supports:

  • binaryArgs on command messages — a Record<string, string> of base64-encoded binary payloads that replace placeholder strings in command arguments
  • binary flag on response messages — when true, the response data is a base64-encoded Buffer

The agent decodes incoming base64 binaryArgs to Buffers before execution, and encodes Buffer results back to base64 for transport.

HGETFIELD_BUFFER virtual command — A new virtual command that retrieves a single hash field as a raw Buffer via hgetBuffer(). Used by the monitor to fetch vector
embeddings from source keys before performing KNN search.

v0.8.0 New feature
Notable features
  • Hot Keys tab ranking top 50 keys by LFU frequency or idle time with visual bars, color coding, rank movement indicators, pattern chips, and tier‑based retention (Community 7 days, Pro 30 days, Enterprise unlimited).
Full changelog

Hot Key Tracking

Track your hottest keys in real time. The new Hot Keys tab on the Key Analytics page ranks the top 50 keys by access
signal and shows how rankings shift over time.

How it works:

  • During each analytics collection cycle, per-key metrics are captured via pipeline commands (OBJECT FREQ, OBJECT IDLETIME, MEMORY USAGE, TTL)
  • Keys are ranked by LFU frequency score (when available) or idle time, and the top 50 are persisted per snapshot
  • Select a date range to compare the current snapshot against a baseline and see rank movement

Features:

  • Automatic detection of LFU vs idle time signal based on your Valkey eviction policy
  • Visual frequency bars for LFU scores (0–255 scale)
  • Color-coded idle time values (red < 60s, amber < 1h)
  • Rank movement indicators showing how keys moved between snapshots
  • Pattern summary chips grouping hot keys by key pattern
  • Top 10 rows highlighted with accent border
  • Tier-based data retention — Community: 7 days, Pro: 30 days, Enterprise: unlimited

Bug Fixes:

  • Fix pipeline error handling when OBJECT FREQ fails on non-LFU instances
  • Fix DateRangePicker dropdown overflow near right edge of viewport (global fix)

What's Changed

  • feat: add hot key tracking with rank movement and tier-based retention by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/46

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.7.0...v0.8.0

agent-v1.1.0 Bug fix
Notable features
  • Collects per-key access metrics enabling Hot Keys feature
Full changelog

Hot Key Tracking Support

The agent now collects per-key access metrics during key analytics scans, enabling the Hot Keys feature introduced in
BetterDB Monitor v0.8.0.

Previously, the agent only returned pattern-level aggregates — individual key details (frequency score, idle time, memory,
TTL) were discarded. Hot key ranking and the Hot Keys tab now work correctly for agent-connected instances (AWS MemoryDB,
ElastiCache, VPC-hosted databases).

Bug Fix

  • Fix pipeline error handling for OBJECT FREQ and OBJECT IDLETIME commands. When a command errors (e.g., OBJECT FREQ
    on a non-LFU instance), iovalkey returns [Error, undefined] — the previous check incorrectly treated undefined as a
    valid value.
v0.7.0 Bug fix
Notable features
  • CPU utilization monitoring with real-time chart and Prometheus gauges
  • I/O thread activity chart showing per-second read/write rates for Valkey's multi-threaded I/O
  • Persistent latency and memory snapshots stored every 60s with 7‑day retention
Full changelog

New Features

  • CPU utilization monitoring — Real-time CPU usage chart (system vs user) on the dashboard with anomaly detection for CPU spikes. Includes Prometheus gauges for
    betterdb_cpu_sys_seconds_total and betterdb_cpu_user_seconds_total. (#41)

  • I/O thread activity chart — New dashboard panel showing per-second read/write rates for Valkey's multi-threaded I/O. Adaptively displays a multi-threaded
    activity chart or a single-threaded guidance card based on server configuration. Persisted to storage for historical viewing. (#44)

  • Persistent latency and memory snapshots — Latency events (LATENCY LATEST), latency histograms (LATENCY HISTOGRAM), and memory stats (including ops/sec, CPU,
    and I/O thread counters) are now polled every 60s and stored for historical analysis. Dashboard and Latency pages support date-range filtering to view stored data.
    Existing deployments upgrade seamlessly via idempotent schema migrations. 7-day retention by default. (#42, #44)

  • Usage telemetry — Tracks app lifecycle and user interaction events (app start, db connect, page views, idle re-engagement). All events are best-effort, contain
    no PII, and respect BETTERDB_TELEMETRY=false. (#39)

  • Key analytics agent support — SCAN-based key analytics collection moved behind DatabasePort, enabling agent-connected databases to proxy key inspection through
    a new COLLECT_KEY_ANALYTICS command. (#34)

Improvements

  • Smarter anomaly detection — Addressed community feedback on detection accuracy:

    • Fragmentation detection now uses allocator_frag_ratio instead of mem_fragmentation_ratio, which can report misleading values due to swap
    • Slowlog detection switched from slowlog_count (which saturates at the configured buffer size and stops detecting new entries) to slowlog_last_id deltas
    • New CRITICAL node_failover alert detects master-to-replica role transitions (#37)
  • Dashboard responsiveness — Overview cards now wrap naturally on narrow viewports. Chart grid switches to single-column at a wider breakpoint. Connection
    management buttons have larger hit targets for better usability. (#45)

  • Key analytics deduplication — Patterns now show only the latest snapshot per pattern, eliminating duplicates. (1dbafb2)

Bug Fixes

  • Postgres UUID handling — Fixed all three storage INSERT paths silently discarding application-generated IDs, which could cause duplicate entries. (#42)

Dependencies

  • Bump fastify from 5.7.4 to 5.8.1 (#38)
  • Bump @nestjs/platform-fastify from 11.1.10 to 11.1.14 (#36)

What's Changed

  • feat: move key analytics SCAN logic into DatabasePort adapter for age… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/34
  • feat: improve anomaly detection for fragmentation, slowlog, and node failovers by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/37
  • feat: add usage telemetry for app lifecycle and user interactions by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/39
  • build(deps): bump @nestjs/platform-fastify from 11.1.10 to 11.1.14 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/36
  • build(deps): bump fastify from 5.7.4 to 5.8.1 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/38
  • feat: add tier-aware data retention service and prune isolation tests by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/40
  • feat: add CPU utilization metrics, anomaly detection, and dashboard p… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/41
  • feat: add persistence for latency events and memory stats by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/42
  • feat: add I/O thread activity chart to dashboard with adaptive single… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/44
  • fix: improve dashboard responsiveness and connection button usability by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/45

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.6.1...v0.7.0

agent-v1.0.2 New feature
⚠ Upgrade required
  • Requires BetterDB Cloud monitor v0.6.0+; compatible with Valkey 7.2+ and Redis 6.0+. No config changes needed – analytics appear automatically within 5 minutes after upgrade.
Notable features
  • COLLECT_KEY_ANALYTICS command provides key pattern distribution, memory usage per pattern, TTL coverage, hot/cold classification, and stale key detection for databases accessed through the agent tunnel.
Full changelog

Release Date: February 27, 2026

What's New

Key Analytics Support

The agent now supports the COLLECT_KEY_ANALYTICS command, enabling full key pattern analysis for databases connected via the agent tunnel. Previously, key analytics required a direct connection to the database — this meant customers monitoring managed services like Amazon MemoryDB or Amazon ElastiCache through the agent couldn't see key distribution, memory usage per pattern, TTL analysis, or hot/cold key classification.

With v0.1.2, the agent performs SCAN and per-key inspection (MEMORY USAGE, OBJECT IDLETIME, OBJECT FREQ, TTL) locally within your VPC and sends the aggregated results back to BetterDB Cloud. This keeps all heavy I/O local to your network — only the summarized pattern data crosses the WebSocket tunnel.

What you get:

  • Key pattern distribution (e.g. user:* is 40% of keys, session:* is 25%)
  • Memory usage per pattern with min/avg/max breakdown
  • TTL coverage analysis — keys with TTL vs without, expiring soon
  • Hot/cold key classification based on access frequency
  • Stale key detection based on idle time

Compatibility

  • Works with Valkey 7.2+ and Redis 6.0+
  • Tested with Amazon MemoryDB for Valkey, Amazon ElastiCache for Valkey, and self-hosted instances
  • Requires BetterDB Cloud monitor v0.6.0+

Upgrade

Pull the new image and restart:

docker rm -f betterdb-agent
docker pull 811740411689.dkr.ecr.us-east-1.amazonaws.com/betterdb-agent:v0.1.2

docker run -d \
  --name betterdb-agent \
  -e BETTERDB_TOKEN=<your-token> \
  -e BETTERDB_CLOUD_URL=wss://<workspace>.app.betterdb.com/agent/ws \
  -e VALKEY_HOST=<your-valkey-host> \
  -e VALKEY_PORT=6379 \
  -e VALKEY_TLS=true \
  811740411689.dkr.ecr.us-east-1.amazonaws.com/betterdb-agent:v0.1.2

No configuration changes required. Key analytics will begin populating automatically within 5 minutes of the agent connecting.

v0.6.1 New feature
Notable features
  • Report fatal startup errors to entitlement server as `startup_error` telemetry events within the first 60 seconds, categorizing connection_refused, port_in_use, auth_failed, timeout, storage_init, and config_invalid; non-fatal Valkey/Redis connection failures also reported.
  • Detect CONFIG command availability on managed Redis services (e.g., AWS ElastiCache, Google Cloud Memorystore) and skip config change monitoring when unavailable via `configAvailable` capability flag.
Full changelog

Bug Fix

  • Handle disabled CONFIG command on managed Redis services (#32) Detects CONFIG availability at connect time and skips config change monitoring when the command is unavailable (e.g. AWS ElastiCache, Google Cloud Memorystore). Adds configAvailable capability flag to the database adapter interface.

New Feature

  • Report startup errors to entitlement server (#33) Captures fatal errors within the first 60 seconds of process lifetime and sends them as startup_error telemetry events. Categorizes errors into connection_refused, port_in_use, auth_failed, timeout, storage_init, and config_invalid. Also reports non-fatal Valkey/Redis connection failures from ConnectionRegistry. Startup error telemetry bypasses the telemetry opt-out to ensure visibility into why users hit errors and bail.

What's Changed

  • fix: handle disabled CONFIG command on managed Redis services (#27) by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/32
  • feat: report startup errors to entitlement server within first 60s by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/33

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.6.0...v0.6.1

agent-v1.0.0 New feature
Notable features
  • Secure WebSocket tunnel enabling monitoring without VPC peering or inbound firewall rules
  • Support for TLS connections to services like ElastiCache and MemoryDB
  • Minimal footprint as a single container with no external dependencies
Full changelog

Initial release of the BetterDB Agent - a lightweight proxy for monitoring Valkey/Redis instances in private networks (VPCs, private subnets) through BetterDB Cloud.

Features

  • Secure WebSocket tunnel to BetterDB Cloud - no VPC peering or inbound firewall rules needed
  • Supports TLS connections (ElastiCache, MemoryDB)
  • Minimal footprint - single container, no dependencies

Installation

Docker

docker pull betterdb/agent:1.0.0

npm

npx @betterdb/agent

Configuration

Connection details and environment variables are provided through the BetterDB Cloud UI when you set up an agent connection in your workspace.

v0.6.0 Breaking risk
Breaking changes
  • API docs endpoint moved from `/api/docs` to `/docs`
  • Version check interval default changed from 6 hours to 1 hour (configurable via `VERSION_CHECK_INTERVAL_MS`)
Security fixes
  • Agent command executor enforces subcommand restrictions (e.g., only `CONFIG GET` allowed)
  • CI pipeline hardened against script injection via environment variables
Notable features
  • BetterDB Cloud – fully managed monitoring with self‑service workspaces, team collaboration, and isolated resources
  • Lightweight agent for monitoring Valkey/Redis instances in private VPCs via secure outbound WebSocket tunnel
Full changelog

Highlights

BetterDB Monitor v0.6.0 is a landmark release. You can now monitor Valkey and Redis instances running in private VPCs -- including AWS ElastiCache and MemoryDB -- without exposing them to the public internet. Deploy a lightweight agent in your network and get full visibility in seconds. This release also introduces BetterDB Cloud, a fully managed option so you can skip self-hosting entirely.

What's New

BetterDB Cloud

A fully managed version of BetterDB Monitor is now available. Sign up with Google or GitHub, create a workspace, invite your team, and start monitoring - no infrastructure to manage.

  • Sign up and start monitoring in under a minute
  • Invite team members by email to collaborate on shared dashboards
  • Each workspace is fully isolated with dedicated resources
  • Connect databases in private networks using the agent (see below)

Visit betterdb.com to get started.

Monitor Databases in Private VPCs

A new lightweight agent lets you monitor Valkey and Redis instances that aren't publicly accessible - such as AWS ElastiCache, MemoryDB, or any database behind a firewall.

Deploy the agent in your VPC and it establishes a secure outbound WebSocket tunnel to BetterDB. No inbound ports, no VPC peering, no security group changes. The agent enforces a strict command whitelist — only read-only monitoring commands are allowed (e.g., INFO, SLOWLOG, CLIENT LIST), and destructive operations like FLUSHALL, SHUTDOWN, or CONFIG SET are blocked entirely.

docker run -d \
  --name betterdb-agent \
  -e VALKEY_HOST=your-elasticache-endpoint \
  -e VALKEY_PORT=6379 \
  -e BETTERDB_CLOUD_URL=wss://your-workspace.betterdb.com/agent/ws \
  -e BETTERDB_TOKEN=your-token \
  betterdb/agent:latest

Or run without Docker:

npx betterdb-agent \
  --valkey-host your-elasticache-endpoint \
  --valkey-port 6379 \
  --cloud-url wss://your-workspace.betterdb.com/agent/ws \
  --token your-token

Generate and manage agent tokens directly from the connection selector in the UI.

Graceful Degradation

When monitoring managed services that restrict certain commands (e.g., ElastiCache blocking SLOWLOG, CLIENT LIST, or ACL LOG), BetterDB now handles this gracefully. Instead of crashing or showing errors, each feature degrades independently - unavailable sections are clearly marked in the UI while everything else continues working normally.

Improved Cluster Visualization

The cluster node graph now pre-calculates positions for a more stable layout. Dragging nodes no longer causes the rest of the graph to jump around.

Slow Log and Command Log

  • SQLite users now have full command log support (previously only available with PostgreSQL)
  • Pattern analysis correctly isolates data per connection

Bug Fixes

  • Page refreshes in production no longer show a blank page (SPA routing fixed)
  • API 404 responses now return JSON instead of HTML
  • Cluster metrics collection is no longer disrupted when slot stats are unavailable
  • Slow log unavailable overlay now correctly references both SLOWLOG and COMMANDLOG
  • Various fixes to Docker and npx instructions shown in the agent setup UI

Security

  • Agent command executor enforces subcommand restrictions (e.g., only CONFIG GET is allowed, not bare CONFIG)
  • CI pipeline hardened against script injection via environment variables

Breaking Changes

  • API docs endpoint moved from /api/docs to /docs
  • Version check interval default changed from 6 hours to 1 hour (configurable via VERSION_CHECK_INTERVAL_MS)

Upgrade Guide

Self-Hosted (Docker)

docker pull betterdb/monitor:0.6.0

All existing configurations are fully backwards compatible. No changes needed.

Cloud

Visit betterdb.com to create a free workspace.

What's Changed

  • basic CLA added by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/25
  • Change CLA branch from 'master' to 'cla-signatures' by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/26
  • fix: pre-calculate cluster node positions and reduce drag disturbance by @Shanb007 in https://github.com/BetterDB-inc/monitor/pull/23
  • Command slowlog polling changes by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/29
  • build(deps): bump axios from 1.13.2 to 1.13.5 by @dependabot[bot] in https://github.com/BetterDB-inc/monitor/pull/21
  • feat: Cloud-version support with multi-tenant provisioning, agent connectivity, and workspace management by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/30

New Contributors

  • @Shanb007 made their first contribution in https://github.com/BetterDB-inc/monitor/pull/23

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.5.0...v0.6.0

v0.5.0 New feature
⚠ Upgrade required
  • API documentation now served at `/docs` (was `/api/docs`).
  • Optional: set `STORAGE_SSL_CA` for cloud PostgreSQL instances requiring SSL certificates.
Notable features
  • Zero‑connection startup with guided UI flow and health endpoint `waiting` status
  • PostgreSQL SSL support via new `STORAGE_SSL_CA` env var for AWS RDS, GCP Cloud SQL, Azure
  • ServerStartupGuard component preventing frontend race conditions
Full changelog

Highlights

This release introduces zero-connection startup — BetterDB Monitor now starts cleanly without any database configured, letting users add connections entirely through the UI. It also adds PostgreSQL SSL support for cloud-hosted databases (AWS RDS, GCP Cloud SQL, Azure), and resolves several reliability issues around SPA routing, startup race conditions, and memory leaks.


New Features

Zero-Connection Startup

BetterDB Monitor no longer requires DB_HOST to be set at startup. The application boots into a guided first-time setup experience, with a new waiting status in health endpoints indicating no connections are configured yet. Users can add their first connection directly from the UI via the sidebar connection selector.

PostgreSQL SSL Support

New STORAGE_SSL_CA environment variable enables SSL connections to cloud-hosted PostgreSQL instances. Supports both local file paths and URLs (with a domain whitelist and 10s fetch timeout), covering AWS RDS, GCP Cloud SQL, and Azure Database for PostgreSQL out of the box.

Server Startup Guard

A new ServerStartupGuard component ensures the frontend waits for full backend initialization before rendering. Includes progress indicators and timeout handling, eliminating the race condition where the UI would attempt API calls before the server was ready.

Improvements

SPA Routing

Fixed client-side routing breaking on page refresh in production. Implemented a SpaFallbackModule with type-safe Fastify handlers and a static file whitelist, using proper NestJS architecture patterns instead of catch-all workarounds.

Enhanced First-Time UX

  • Loading states and error boundaries throughout the application
  • NoConnectionsGuard displays contextual guidance with an arrow pointing to the sidebar connection selector
  • Helpful setup instructions for users with no connections configured

Reliability

  • Proper timeout cleanup in polling components to prevent memory leaks
  • Consistent error messaging across connection and startup flows

Migration

  • Fully backwards compatible — existing DB_HOST configurations work unchanged
  • Optional: Set STORAGE_SSL_CA for cloud PostgreSQL instances requiring SSL certificates
  • API docs now served at /docs instead of /api/docs

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.4.1...v0.5.0

v0.4.1 Security relevant
Security fixes
  • CVE-2026-25223 — Content-Type validation bypass in Fastify (High severity)
  • CVE-2026-25224 — DoS via unbounded memory in Fastify Web Streams (Low severity)
  • GHSA-67mh-4wv8-2f99 — Overly permissive CORS configuration in esbuild dev server (Moderate severity)
Notable features
  • Added BetterDB CLI package with build/publish workflow, documentation, and tooling
Full changelog

Security

fastify — Upgraded to v5.7.3 to address two vulnerabilities:

  • Content-Type validation bypass — Appending a tab character to the Content-Type header allowed attackers to completely bypass request body validation while the server still parsed the body normally. This affects any handler relying on Content-Type-based schema validation for data integrity or security. (CVE-2026-25223, High severity)
  • DoS via unbounded memory in Web Streams — A slow or non-reading client could trigger unbounded memory buffering when using ReadableStream via reply.send(), potentially leading to process crashes. (CVE-2026-25224, Low severity)

esbuild — Upgraded to v0.25.0 to fix an overly permissive CORS configuration in the development server. The default Access-Control-Allow-Origin: * header allowed any website to read responses from the dev server, potentially leaking source code. (GHSA-67mh-4wv8-2f99, Moderate severity)


What's Changed

  • Add BetterDB CLI package with build/publish workflow, docs, and tooli… by @KIvanow in https://github.com/BetterDB-inc/monitor/pull/17

Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.4.0...v0.4.1

v0.4.0 Breaking risk
⚠ Upgrade required
  • Backup your data before upgrading.
  • Update API clients to use PATCH instead of PUT for webhook updates.
  • Add additional database connections via the UI selector or POST /connections endpoint.
Breaking changes
  • PUT /webhooks/:id endpoint removed; use PATCH /webhooks/:id instead
Notable features
  • Multi-Database Connection Support with UI selector and per‑connection metrics/alerts
  • Connection‑Scoped Webhooks including connection context in payloads
  • Keyless Community Tier granting early access to beta Pro/Enterprise features
Full changelog

Multi-Database Connection Support

Connect to and monitor multiple Valkey/Redis instances from a single BetterDB Monitor deployment.

  • Connection selector in the UI to switch between databases - all dashboards, analytics, logs, and alerts update to reflect the selected connection
  • Per-connection metrics, alerts, and webhooks - each database is monitored independently
  • X-Connection-Id header for API requests to target specific connections
  • Credential status tracking with clear feedback on connection issues
  • Existing single-database setups continue to work unchanged

Version Update Notifications

Automatic update checking notifies you when a new release is available.

  • Dismissible banner in the UI with direct link to release notes
  • Version info piggybacked on license/telemetry requests

Keyless Community Tier

No license key needed to get started. Community tier users now automatically get early access to upcoming Pro and Enterprise features as they enter beta - try them before they move to paid tiers. Non-blocking background validation and graceful degradation on network failures.

Connection-Scoped Webhooks

Webhooks can now be scoped to specific database connections with proper isolation. Connection context is included in webhook payloads.

Improvements

  • MultiConnectionPoller base class for standardized polling with error isolation between connections
  • Immutable state management prevents subtle bugs from shared object references
  • Configurable encryption salt via ENCRYPTION_KEK_SALT for defense-in-depth
  • Rate limiting on license refresh endpoint (5 requests/minute)
  • Connection-aware AI assistant — chatbot can query specific database connections
  • Zod-based environment validation that fails fast on invalid config at startup
  • PostgreSQL migration safety — constraint additions check for duplicates before applying
  • Docker Compose v2 syntax support

Breaking Changes

  • PUT /webhooks/:id is now PATCH /webhooks/:id — update your API clients accordingly

New Environment Variables

Variable | Default | Description
-- | -- | --
ENCRYPTION_KEK_SALT | betterdb-kek-salt-v1 | Custom salt for encryption key derivation
VERSION_CHECK_INTERVAL_MS | 21600000 | Version check interval (default: 6 hours)

Upgrade Notes

  1. Backup your data before upgrading
  2. Update API clients to use PATCH instead of PUT for webhook updates
  3. To add additional connections, use the connection selector in the UI or POST /connections

Full Changelog: https://github.com/betterdb-inc/monitor/compare/v0.3.0...v0.4.0

v0.3.0 New feature
Notable features
  • Per-webhook thresholds (memoryCriticalPercent, connectionCriticalPercent) with defaults
  • Per-webhook delivery settings (timeoutMs, maxResponseBodyBytes)
  • Per‑webhook alert hysteresisFactor and Advanced Configuration UI section
Full changelog

Per-Webhook Configuration

Each webhook can now have its own thresholds, delivery settings, and alert behavior. This enables tiered alerting where different notification channels trigger at different severity levels.

Example use case:

  • Slack webhook triggers at 75% memory usage for early warning
  • PagerDuty webhook triggers at 95% for critical alerts only

New Configuration Options

| Option | Description |
|--------|-------------|
| thresholds.memoryCriticalPercent | Custom memory alert threshold (default: 90) |
| thresholds.connectionCriticalPercent | Custom connection alert threshold (default: 90) |
| deliveryConfig.timeoutMs | Request timeout per webhook (default: 30000) |
| deliveryConfig.maxResponseBodyBytes | Response body storage limit (default: 10000) |
| alertConfig.hysteresisFactor | Recovery threshold multiplier (default: 0.9) |

UI Improvements

  • New Advanced Configuration section in webhook form for power users

Fixes

  • Fixed DI injection tokens for proprietary webhook services
  • Fixed PostgreSQL retry query timestamp comparison
  • Handle duplicate anomaly events gracefully with upsert
  • Use Docker Compose v2 command syntax

Improvements

  • DLQ service now respects per-webhook maxRetries setting
  • Webhook Pro module marked as global for proper DI resolution

Full Changelog: https://github.com/betterdb-inc/monitor/compare/v0.2.0...v0.3.0

v0.2.0 New feature
Notable features
  • Real-time HTTP webhooks with HMAC-SHA256 signatures, automatic exponential backoff retries, delivery history, and health monitoring (tier‑specific events).
  • Slow Log Analytics: persistent storage across PostgreSQL, SQLite, or in‑memory backends with UI date‑range filtering, pattern analysis, and client attribution.
  • Enterprise ACL & Config Monitoring: alerts on ACL changes and CONFIG SET operations.
Full changelog

Webhooks

Real-time HTTP notifications for monitoring events. Integrate easily with third party systems

Events by tier:

  • Free: instance.down, instance.up, memory.critical, connection.critical, client.blocked
  • Pro: anomaly.detected, slowlog.threshold, latency.spike, connection.spike, replication.lag, cluster.failover
  • Enterprise: acl.modified, config.changed, acl.violation, audit.policy.violation, compliance.alert

Features: HMAC-SHA256 signatures, automatic retries with exponential backoff, delivery history, health monitoring.

Slow Log Analytics

Persistent storage for slow log and command log entries with historical querying.

  • Date range filtering via UI
  • PostgreSQL, SQLite, or in-memory storage backends
  • Pattern analysis and client attribution

Enterprise: ACL & Config Monitoring

Detects and alerts on ACL user/permission changes and CONFIG SET operations.


See docs/webhooks.md for full documentation.

v0.1.1 New feature
⚠ Upgrade required
  • Requires PostgreSQL, SQLite, or in‑memory storage; configure via STORAGE_TYPE and STORAGE_URL environment variables.
  • Docker image supports linux/amd64 and linux/arm64 platforms.
  • Beta access needs BETTERDB_LICENSE_KEY set to BETA-TEST for full Pro features.
Notable features
  • Historical persistence of slowlog, client connections, ACL audit trail, and anomaly events
  • Pattern analysis for slow queries (e.g., GET user:* usage) and COMMANDLOG large request/reply patterns
  • Anomaly detection with automatic baseline calculation and Z‑score alerts across 15+ metrics
Full changelog

BetterDB Monitor v0.1.1

The first public beta release of BetterDB Monitor — a Valkey-first observability platform with historical persistence, pattern analysis, and anomaly detection.

Highlights

🎯 Valkey-first, Redis-compatible — Full support for Valkey 8.0+ with graceful degradation for Redis 7+

📊 Historical persistence — Query what happened at 3am, not just what's happening now

🔍 Pattern analysis — See that GET user:* is 80% of your slow queries

COMMANDLOG support — Valkey 8.1+ exclusive feature for tracking large requests/replies

🚨 Anomaly detection — Automatic baseline detection with Z-score analysis

Features

Real-Time Monitoring

  • Live dashboard with auto-refresh (5s default)
  • INFO metrics: memory, CPU, connections, replication
  • Client list with connection details and filtering
  • Slowlog viewer with historical persistence
  • Memory Doctor and Latency Doctor diagnostics
  • Database health checks with capability detection

Valkey-Exclusive Features (8.1+)

  • COMMANDLOG — Track commands by execution time, request size, and reply size
  • COMMANDLOG patterns — Aggregate analysis of large request/reply patterns
  • CLUSTER SLOT-STATS — Per-slot metrics for cluster deployments

Historical Analytics

  • Slowlog history with configurable retention
  • Client connection snapshots over time
  • ACL audit trail persistence
  • Anomaly event history

Pattern Analysis

  • Slowlog pattern aggregation (e.g., "HGETALL * is 45% of slow queries")
  • COMMANDLOG pattern analysis for large requests/replies
  • Spike detection for unusual activity

Cluster Support

  • Automatic node discovery
  • Cluster topology visualization
  • Aggregated metrics across all nodes
  • Slot distribution and migration tracking
  • Per-node slowlog aggregation

Security & Compliance

  • ACL audit trail with historical persistence
  • ACL denied events by reason and user
  • Connection tracking by ACL user

Prometheus Integration

  • 99 unique metrics exposed at /prometheus/metrics
  • Ready-to-use PromQL queries
  • Alertmanager rules included in documentation
  • Compatible with Grafana, Datadog, and other tools

Anomaly Detection

  • Automatic baseline calculation
  • Z-score based detection across 15+ metrics
  • Configurable sensitivity
  • Prometheus metrics for anomaly events

Deployment

Docker (Recommended)

docker run -d \
  --name betterdb-monitor \
  -p 3001:3001 \
  -e DB_HOST=your-valkey-host \
  -e DB_PORT=6379 \
  -e DB_PASSWORD=your-password \
  -e BETTERDB_LICENSE_KEY=BETA-TEST \
  -e STORAGE_TYPE=postgres \
  -e STORAGE_URL=postgresql://user:pass@host:5432/db \
  betterdb/monitor:0.1.1

🎁 Beta Access: Use license key BETA-TEST to unlock all Pro features during the beta period.

Supported Platforms

  • linux/amd64
  • linux/arm64

Storage Backends

  • PostgreSQL — Recommended for production
  • Memory — For testing/evaluation (no persistence)
  • SQLite — Available when running locally from source (not included in Docker image)

Compatibility

| Database | Version | Support Level |
|----------|---------|---------------|
| Valkey | 8.1+ | Full (all features) |
| Valkey | 8.0 | Full (no COMMANDLOG) |
| Valkey | 7.x | Core features |
| Redis | 7+ | Core features |

Documentation

What's Next

  • VS Code extension for Valkey
  • Hosted SaaS platform
  • Webhook notifications
  • Migration CLI tools

Beta — feedback welcome: [email protected]