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
Observability + SemanticCache + Embedding helpers
MONITOR Capture Sessions, Anomaly Detection, Telemetry
- 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
- 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.
- 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_shakemode now correctly emitscluster = trueon 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
DBSIZEandused_memoryacross all master shards. Previous releases reported one shard's totals as the cluster total.
Upgrade
docker pull betterdb/monitor:latest
- 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
isDemoflag on tenants — provisioning a demo tenant creates a second Ingress rule, a Route53 CNAME alias, and setsDEMO_HOSTNAME/COOKIE_DOMAINon the tenant pod - DemoModeGuard — mutations and sensitive reads (settings, webhooks, team) return 404 on the demo host
- Frontend demo UI —
DemoContext,DemoBanner, andDemoGuardedRoutehide write actions and nav items (Team, Webhooks, Settings) in demo mode; locked items show as inactive with a tooltip - Redesigned
NoConnectionsGuardempty state with an inline "or try live demo" CTA - Server-side PostHog telemetry for
demo_workspace_loadedanddemo_link_clickedevents (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 configuredPOSTHOG_HOST - Vite dev server proxies
/ingestto 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.codein addition toerror.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_modulesis 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.jsonto exclude spec files from the NestJS production build - Fixed PostHog proxy global prefix exclusion (
/ingestwas being mounted under/api/ingestin 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
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
- Requires Valkey 8+ with the valkey-search module for vector index support
- Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB
- 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.
- 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.
- 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 -
SemanticCachepolls{prefix}:__configevery 30s and updatesdefaultThreshold/categoryThresholdsin-memory. First refresh fires synchronously oninitialize()so a
freshly-started process picks up an already-applied proposal immediately. Configure via the newconfigRefreshoption; opt out withconfigRefresh: { enabled: false }. New Prometheus counter
{prefix}_config_refresh_failed_total. refreshConfig()- public method returningbooleanfor manual refresh.threshold_adjustcapability - added to the discovery marker'scapabilitiesarray.ConfigRefreshOptionstype exported from package root.
Changed
- Constructor values for
defaultThresholdandcategoryThresholdsare now used as fallbacks when the corresponding fields are absent from__config.
Behavior change
- A
{prefix}:__configValkey hash that previously had no effect now drivesdefaultThresholdandcategoryThresholdsat runtime. Audit existing keys before upgrading, or setconfigRefresh: { enabled: false }to keep constructor values authoritative.
0.3.0
Added
- Discovery marker protocol - on
initialize()the cache registers itself in__betterdb:cachesand writes a periodic__betterdb:heartbeat:<name>key (default 30s). Lets BetterDB Monitor enumerate live
caches without manual config. Newdispose()method. Newdiscovery_write_failed_totalPrometheus 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
- `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
- 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 -
AgentCachepolls{name}:__tool_policiesevery 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 newconfig_refreshoption; opt out withconfig_refresh=ConfigRefreshOptions(enabled=False). New Prometheus counter
{prefix}_config_refresh_failed_total. ToolCache.refresh_policies()- public method returningboolfor 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:cachesand writes a periodic__betterdb:heartbeat:<name>key (default 30s). Lets BetterDB Monitor enumerate live
caches without manual config. Newdiscoveryoption. Newdiscovery_write_failed_totalPrometheus counter.shutdown()stops the heartbeat.
- 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 refresh —
AgentCachepolls{name}:__tool_policiesevery 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 newconfigRefreshoption; opt out withconfigRefresh: { enabled: false }. New Prometheus counter{prefix}_config_refresh_failed_total. ToolCache.refreshPolicies()— public method returningbooleanfor 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:cachesand writes a periodic__betterdb:heartbeat:<name>key (default 30s). Lets BetterDB Monitor enumerate live
caches without manual config. NewensureDiscoveryReady()for strict name-collision enforcement. NewToolCache.listPolicyNames(). Newdiscovery_write_failed_totalPrometheus 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
- 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
- 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 bycache_namecache_get_proposal- fetch a single proposal by id including its audit trailcache_approve_proposal- synchronously approve and applycache_reject_proposal- reject with optional reasoncache_edit_and_approve_proposal- editnew_thresholdornew_ttl_secondsand 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.jsonregistry version synced to1.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
- 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_proposalsandcache_proposal_audittables, 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 aggregateread(GET/MGET) andwrite(SET/HSET-family). - Source advisory showing the active
commandlog/slowlogdirective and configured threshold, so percentiles can be qualified correctly. - Indexing-event correlation: raises a
latency_degraded_during_indexingannotation 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.breachwebhook 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}:__configon a configurable interval (default 30s); first refresh fires synchronously oninitialize(). - New
refreshConfig()public method andConfigRefreshOptionsexport. threshold_adjustcapability added to the discovery marker.- Behavior change: a
{prefix}:__confighash that previously had no effect now drivesdefaultThreshold/categoryThresholdsat runtime. SetconfigRefresh: { enabled: false }to keep constructor
values authoritative.
@betterdb/semantic-cache 0.3.0
- Discovery marker protocol: registers in
__betterdb:cachesoninitialize(), writes a 30s periodic heartbeat key. Newdispose()method anddiscovery_write_failed_totalPrometheus counter.
@betterdb/agent-cache 0.6.0
- Periodic config refresh: polls
{name}:__tool_policiesevery 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. NewToolCache.listPolicyNames()anddiscovery_write_failed_totalcounter.
betterdb-agent-cache (Python) 0.5.0 → 0.6.0
- Discovery marker protocol and periodic config refresh, matching the TypeScript releases.
Improvements
WebhookRepositoryextracted 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/sharedpath aliases in the web app'stsconfigthat 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
- 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
- Requires Valkey 8+ with the valkey-search module (vector index support). Works with ElastiCache, Memorystore, and MemoryDB for Valkey.
- 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.
- 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
- 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.
Minor fixes and improvements.
Changelog
Updated release flow
- Requires Python 3.11+ and Valkey 8+ with the `valkey-search` module installed
- Works with ElastiCache for Valkey, Memorystore for Valkey, and MemoryDB
- 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
- 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`.
- 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
- 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.
- 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.
- 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
-
- A default cost table sourced from LiteLLM's
model_prices_and_context_window.jsonis
now bundled with the package and refreshed on every release
- A default cost table sourced from LiteLLM's
- 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
- 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 usingbg-whitewithout a corresponding dark text override, making them unreadable in dark mode. Fixed withdark: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-idheader 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
- 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,responseFormatreasoningEffort— for extended thinking modelspromptCacheKey— 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_outputitems withnullorundefinedoutput 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
- 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)
- @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:
- CVE-2026-6410 (GHSA-pr96-94w5-mx2h)
- CVE-2026-6414 (GHSA-x428-ghpx-8j92)
vite 8.0.2 → 8.0.5
Multiple path traversal and filesystem boundary bypass fixes in the dev server:
server.fschecks 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 Similarbutton 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
- 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.
- 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.
- 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
- 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) -BetterDBLlmCacheimplementingBaseCache. Plugs intoChatOpenAI'scacheoption. Auto-extracts token counts fromusage_metadatafor cost tracking. - Vercel AI SDK (
@betterdb/agent-cache/ai) -createAgentCacheMiddleware()implementingLanguageModelMiddleware. Intercepts non-streamingdoGeneratecalls. Cache hits includeproviderMetadata: { agentCache: { hit: true } }. - LangGraph (
@betterdb/agent-cache/langgraph) -BetterDBSaverimplementingBaseCheckpointSaver. 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%), ordecrease_ttl_or_disable(<40%).- Cost tracking via
costTableconfig - provide model pricing, and cache hits automatically accumulate savings.
Error handling
AgentCacheErrorbase class,AgentCacheUsageErrorfor caller mistakes (colons in tool names, glob chars in thread IDs),ValkeyCommandErrorfor 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, notdoStream). 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: 1fast path readscheckpoint:latestdirectly. For threads with thousands of large checkpoints, considerlanggraph-checkpoint-rediswith 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
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
- 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.
- 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.
CONFIGwithout a subcommand is rejected),SENTINELandSLOWLOG RESET
removed from the allowlist. - Unsafe — opt in with
BETTERDB_UNSAFE_CLI=trueto allow writes; surfaces a startup warning and anunsafeCliEnabledflag in the health response.
- Safe (default) — read-only allowlist, 18 destructive commands blocked, bare-subcommand bypass closed (e.g.
- Backend (
apps/api/src/cli/): newCliGatewayWebSocket endpoint at/cli/wswith 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 dedicatedBetterDB-CLIValkey client via a newDatabasePort.call(..., { cli })
adapter API. - Frontend: collapsible
CliPanelwithCtrl+`shortcut, ref-based history navigation (no re-render cascade),sessionStoragepersistence, and an auto-reconnecting WebSocket hook
with exponential backoff. Built-in commands:help,clear,history,exit. - Shared: command parser and
checkSafeMode/checkBlockedfilters centralized in@betterdb/sharedso 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/activateendpoint, persists activated keys to disk, hardened error handling and message extraction. - Entitlement service: new
/v1/registrationsendpoint creates or resends Enterprise licenses and delivers them via Resend; cloud entitlement resolution now keys offtenantId; 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 auseIsMobilehook. - Responsive collapsible sidebar with persisted open/closed state;
CliPanelrepositioned to follow the sidebar viapeer-data-[state]. - Print styles updated to hide the new sidebar.
Bumps
@betterdb/agent1.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=trueto allow writes; this is intentionally a deploy-time decision, not a UI toggle. - Cloud-mode deployments must permit
/cli/wsthrough the auth middleware (already whitelisted in this release). - If you use the new registration flow, configure
VITE_REGISTRATION_URLandENTITLEMENT_URLand ensure the entitlement service has aRESEND_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
- 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
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
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
- 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
- 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
- Pin axios to 1.14.0 to prevent compromised version 1.14.1
- Override rollup, minimatch, and flatted packages to resolve CVEs
- 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
- 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)
- 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
- 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.overridesto prevent resolution to the compromised version. - Transitive CVE overrides - forced
rollup >=4.59.0,minimatch >=3.1.4, andflatted >=3.4.2to 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
- 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
- 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
SemanticCacheclass — 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 diagnosticsstore(prompt, response, options?)— stores prompt/response pairs with optional TTL, category tag, and model taginvalidate(filter)— batch delete by valkey-search filter expression (e.g.@model:{gpt-4o}); returns deleted count and truncation flagstats()— hit/miss/total counts and hit rate, persisted in ValkeyindexInfo()— index metadata fromFT.INFOflush()— 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, andcache.categoryattributes - Four Prometheus metrics:
{prefix}_requests_total,{prefix}_similarity_score,{prefix}_operation_duration_seconds,{prefix}_embedding_duration_seconds - Custom prom-client
Registrysupport for library/multi-tenant contexts
Framework adapters
@betterdb/semantic-cache/langchain—BetterDBSemanticCacheextending LangChainBaseCache, with optionalfilterByModelscoping@betterdb/semantic-cache/ai—createSemanticCacheMiddlewarefor Vercel AI SDK (wrapLanguageModel)
Configuration
- Per-category threshold overrides via
categoryThresholds - Uncertainty band: hits within
uncertaintyBandof the threshold are returned withconfidence: 'uncertain' - Sliding TTL refresh on cache hits
Valkey Search 1.2 compatibility
Verified against valkey-search module v66048. Four divergences from Redis/RediSearch handled:
FT.INFOerror message format differs — all three known patterns matched for cross-compatibilityFT.DROPINDEX DD(Delete Documents flag) not supported — key cleanup done viaSCAN+DEL- KNN score aliases cannot be used in
RETURNorSORTBY— results returned withoutRETURNclause, pre-sorted by distance - Vector field dimension nested inside
"index"sub-array as"dimensions"rather than top-levelDIMkey
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
- 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.
- 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 (default3001)--storage sqlite|memory- storage backend (defaultsqlite, 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 savingadd_connection- register a new connection, optionally set as defaultremove_connection- remove a connection by IDset_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
- 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
- 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
- Requires @betterdb/shared v0.10.0; update agent to v1.3.0 and restart to enable new vector search features in the monitoring UI.
- 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 toFT.SEARCH *sampling whenFT.TAGVALSis 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 optionalLIMITEDmode. 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.PROFILEargument order — TheLIMITEDflag is now correctly placed beforeQUERY, matching the documented command syntax.
Dependencies
- Requires
@betterdb/sharedv0.10.0 (addsVectorIndexSnapshotandVectorIndexSnapshotQueryOptionstypes).
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.
- 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.CREATEcommand 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.CREATEtemplate with recommendedMandEF_CONSTRUCTIONparameters. -
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
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
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
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
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
- 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
- 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
- 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
- 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.
- 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 FREQfails 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
- 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 FREQandOBJECT IDLETIMEcommands. When a command errors (e.g.,OBJECT FREQ
on a non-LFU instance), iovalkey returns[Error, undefined]— the previous check incorrectly treatedundefinedas a
valid value.
- 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_totalandbetterdb_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 respectBETTERDB_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 newCOLLECT_KEY_ANALYTICScommand. (#34)
Improvements
-
Smarter anomaly detection — Addressed community feedback on detection accuracy:
- Fragmentation detection now uses
allocator_frag_ratioinstead ofmem_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) toslowlog_last_iddeltas - New CRITICAL
node_failoveralert detects master-to-replica role transitions (#37)
- Fragmentation detection now uses
-
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
- 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.
- 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.
- 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
configAvailablecapability 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_errortelemetry 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
- 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.
- 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`)
- Agent command executor enforces subcommand restrictions (e.g., only `CONFIG GET` allowed)
- CI pipeline hardened against script injection via environment variables
- 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 GETis allowed, not bareCONFIG) - CI pipeline hardened against script injection via environment variables
Breaking Changes
- API docs endpoint moved from
/api/docsto/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
- API documentation now served at `/docs` (was `/api/docs`).
- Optional: set `STORAGE_SSL_CA` for cloud PostgreSQL instances requiring SSL certificates.
- 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
NoConnectionsGuarddisplays 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_HOSTconfigurations work unchanged - Optional: Set
STORAGE_SSL_CAfor cloud PostgreSQL instances requiring SSL certificates - API docs now served at
/docsinstead of/api/docs
Full Changelog: https://github.com/BetterDB-inc/monitor/compare/v0.4.1...v0.5.0
- 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)
- 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
ReadableStreamviareply.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
- 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.
- PUT /webhooks/:id endpoint removed; use PATCH /webhooks/:id instead
- 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-Idheader 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
MultiConnectionPollerbase 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_SALTfor 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/:idis nowPATCH /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
- Backup your data before upgrading
- Update API clients to use
PATCHinstead ofPUTfor webhook updates - 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
- 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
maxRetriessetting - 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
- 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.
- 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.
- 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-TESTto unlock all Pro features during the beta period.
Supported Platforms
linux/amd64linux/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