Skip to content
Eight Effect-native API SDKs are live.Explore the catalog
Distilled
Esc
navigateopen⌘Jpreview
On this page

Announcing the Distilled OpenSearch SDK

Search, index, inspect, and administer OpenSearch clusters through 684 Effect-native operations.

Search systems sit on a demanding boundary: workloads are concurrent, responses can be large, cluster health changes under load, and transient failures are normal rather than exceptional. @kevinmichaelchen/distilled-opensearch brings 684 official OpenSearch REST operations into Effect with runtime schemas and explicit operational policy.

OpenSearch, at a glance

OpenSearch is an open-source search and analytics suite used for full-text search, observability, log analytics, vector search, and security analytics. Its REST API covers documents, indexes, mappings, queries, aggregations, snapshots, cluster administration, and a broad plugin ecosystem. The project maintains its machine-readable source of truth in opensearch-project/opensearch-api-specification.

Why Effect and Distilled?

OpenSearch work rarely ends with one request. An ingestion flow may create an index, bulk-write documents, wait for a refresh, verify cluster health, and retry only the failures that are safe to repeat. Effect gives that sequence one model for typed failures, timeouts, backoff, concurrency, cancellation, tracing, and dependency injection.

Distilled adds a reviewable API boundary. Inputs and outputs are backed by runtime schemas where the official contract is tractable; known HTTP statuses become typed errors; retry hints are preserved; secrets are redacted; and configuration is an explicit layer that tests can replace. The result is a better fit for long-lived search infrastructure than a bag of loosely related promise calls.

How we made the SDK

Use OpenSearch's source of truth

The project maintains modular YAML and publishes a merged OpenAPI 3.1 file specifically for clients and documentation.

Mirror the published artifact

A dedicated source repository converts only YAML syntax to deterministic JSON and records each upstream revision in immutable Git history.

Generate the complete surface

The shared Alchemy-style generator emits 684 committed operations spanning core search, indexes, snapshots, security, ML, observability, and plugins.

Add cluster-aware runtime policy

The handwritten layer supports basic, bearer, or deliberately absent authentication, decodes OpenSearch error envelopes, and exposes retry composition.

No prose was scraped into a pseudo-spec, and no generated file is edited by hand. The SDK pins an exact source commit, applies reviewable RFC 6902 patches only when needed, and fails CI if regeneration drifts.

Code Examples

Set OPENSEARCH_URL and your cluster credentials, then install:

npm install @kevinmichaelchen/distilled-opensearch effect
pnpm add @kevinmichaelchen/distilled-opensearch effect
bun add @kevinmichaelchen/distilled-opensearch effect
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
import {
  CredentialsFromEnv,
  clusterHealth0,
  indicesCreate0,
  search2,
} from "@kevinmichaelchen/distilled-opensearch";

const OpenSearchLive = Layer.mergeAll(
  FetchHttpClient.layer,
  CredentialsFromEnv,
);

Search an index

Run a query-string search across an index pattern and return the most recent matching logs.

const searchRecentErrors = search2({
  index: "application-logs-*",
  q: "level:error AND service:checkout",
  size: 25,
  sort: "@timestamp:desc",
}).pipe(Effect.provide(OpenSearchLive));

Create an index

Create a versioned application-log index with explicit shard settings and a small mapping.

const createLogIndex = indicesCreate0({
  index: "application-logs-2026.07",
  settings: {
    number_of_shards: 3,
    number_of_replicas: 1,
    refresh_interval: "5s",
  },
  mappings: {
    properties: {
      "@timestamp": { type: "date" },
      level: { type: "keyword" },
      message: { type: "text" },
    },
  },
}).pipe(Effect.provide(OpenSearchLive));

Wait for cluster health

Gate an ingestion or deployment workflow until the cluster reaches at least yellow health.

const waitForClusterHealth = clusterHealth0({
  wait_for_status: "yellow",
  timeout: "30s",
}).pipe(Effect.provide(OpenSearchLive));

The same package can create indexes and mappings, index or update documents, run Query DSL searches and aggregations, manage snapshots, inspect nodes, and call supported plugin APIs.

OpenSearch’s dotted operation IDs become ordinary TypeScript camelCase names, so cluster.health.0 is exported as clusterHealth0. Numeric suffixes remain because the official specification models each HTTP method and path form as a distinct operation; for example, search2 is the indexed GET /{index}/_search variant.

Available now

Read the OpenSearch SDK guide, inspect the implementation, browse the spec mirror, or install @kevinmichaelchen/distilled-opensearch.

Last updated on July 15, 2026

Was this page helpful?