DEV Community

Cover image for Rack-style middleware for vector databases in Ruby: vectra-client 1.1.0
Stokry
Stokry

Posted on

Rack-style middleware for vector databases in Ruby: vectra-client 1.1.0

If you’re building serious AI features in Ruby (semantic search, RAG, recommendations), you quickly realize you don’t just need a client for your vector database — you need a production toolkit.

With vectra-client 1.1.0, the gem gets exactly that: Rack-style middleware for vector databases plus production patterns Ruby/Rails developers already know.

Why this matters

Vectra is aiming to be the most complete production toolkit in the Ruby vector DB ecosystem:

  • Production patterns: 7+ built-in patterns (batch upsert, health check, ActiveRecord integration, reindex, caching…)
  • Middleware: 5 built-in middlewares (the only gem with this approach)
  • Multi-provider: 5 providers behind a unified API (:pinecone, :qdrant, :weaviate, :pgvector, :memory)

The core idea: everything you already know from Rack/Faraday land, now applied to AI / vector workloads.

Positioning:

“The only Ruby gem with Rack-style middleware for vector databases — production patterns you already know, applied to AI workloads.”

What’s new in vectra-client 1.1.0?

1. Rack-style middleware stack for all operations

All public operations on Vectra::Client now go through a middleware stack:

  • upsert, query, fetch, update, delete
  • list_indexes, describe_index, stats
  • create_index, delete_index, list_namespaces

Which means you can:

  • add logging / retry / instrumentation globally
  • add per-client middleware (e.g. PII redaction only for a specific index)
require "vectra-client"

# Global middleware
Vectra::Client.use Vectra::Middleware::Logging
Vectra::Client.use Vectra::Middleware::Retry, max_attempts: 3
Vectra::Client.use Vectra::Middleware::CostTracker

client = Vectra::Client.new(
  provider: :qdrant,
  index: "products",
  namespace: "tenant-1",
  middleware: [
    Vectra::Middleware::PIIRedaction,
    Vectra::Middleware::Instrumentation
  ]
)
Enter fullscreen mode Exit fullscreen mode

Every call (client.upsert, client.query, …) now flows through the same, consistent pipeline.

2. Built-in middleware (production-ready)

Version 1.1.0 ships with 5 ready-to-use middlewares:

  • Logging – structured logs for all operations + duration in ms
  • Retry – retry logic for rate limit / network / timeout errors
  • Instrumentation – hooks for metrics and APM (Datadog, New Relic, Prometheus…)
  • PIIRedaction – PII redaction in metadata before sending to the vector DB
  • CostTracker – simple cost estimation per operation (per provider, per vector)

The point: you can add observability and safety without forking the gem.

3. A client that understands “context”

Vectra::Client now has:

  • default index & namespace (via index: and namespace: on init)
  • helpers:
client.with_index("shadow-products") do |ctx|
  ctx.upsert(vectors: batch)
end

client.with_namespace("tenant-42") do |ctx|
  ctx.query(vector: embedding, top_k: 10)
end

client.with_index_and_namespace("products", "tenant-1") do |ctx|
  ctx.delete(ids: ["products_123"])
end
Enter fullscreen mode Exit fullscreen mode

This makes multi-tenant, shadow indexes, migrations and A/B testing much easier without duplicating a ton of boilerplate.

Using this in a Rails app

Fastest path:

  1. Add the gem:
gem "vectra-client"
Enter fullscreen mode Exit fullscreen mode
  1. Run the install generator:
rails generate vectra:install
Enter fullscreen mode Exit fullscreen mode
  1. Run the index generator for your model (e.g. Product):
rails generate vectra:index Product embedding dimension:1536 provider:qdrant
Enter fullscreen mode Exit fullscreen mode
  1. Include the generated concern and use has_vector + the reindex_vectors helper:
class Product < ApplicationRecord
  include ProductVector
end
Enter fullscreen mode Exit fullscreen mode

Now you can:

  • automatically index embeddings after save
  • run semantic search via Product.vector_search(...)
  • reindex the entire table via Product.reindex_vectors

When does vectra-client make sense?

If you’re building:

  • e‑commerce search (semantic + filters)
  • blog / docs search (hybrid: keyword + vectors)
  • RAG chatbot pulling context from PostgreSQL + pgvector
  • multi-tenant SaaS with namespace isolation
  • recommendation systems (similar products / articles)

…then production features (middleware, health check, batch, reindex, provider-agnostic API) matter a lot more than a barebones “client”.

Wrap-up

The Ruby ecosystem finally gets a serious, production-grade toolkit for working with vector databases:

  • Rack-style middleware you already understand
  • production patterns mapped onto AI workloads
  • a multi-provider API that doesn’t lock you into a single vendor

If you want to see it in action, check out:

If you’d like an example for a specific stack (Sidekiq, Hanami, dry-rb, …), open an issue — this middleware layer is designed exactly for those kinds of extensions.

GitHub repo: stokry/vectra

Top comments (0)