Client SDKs

One native Go SDK plus eight HTTP client libraries. Integrate RLAAS in minutes, regardless of your tech stack.

SDK Overview

Every SDK provides the same functionality:

  • Decision: check, acquire, release
  • Policy CRUD: list, get, create, update, delete
  • Lifecycle: validate, rollout, rollback
  • History: audit, versions
  • Analytics: summary
SDKLanguageHTTP LibraryLocation
GoGo 1.25+Native engine (embedded)pkg/rlaas/
PythonPython 3.8+requestssdk/python/
TypeScriptTypeScript / Node.jsfetchsdk/typescript/
Node.jsNode.js 16+ (plain JS)http / https (stdlib)sdk/nodejs/
JavaJava 11+java.net.http.HttpClientsdk/java/
.NET.NET 8HttpClientsdk/dotnet/
C++C++17 / CMakelibcurl + nlohmann/jsonsdk/cpp/
RustRust 2021 editionreqwest + tokiosdk/rust/
RubyRuby 3.0+ / Rails 7+net/http (stdlib)sdk/ruby/

Go

Go SDK (Embedded)

The Go SDK is the native library — import it and evaluate decisions locally with zero network overhead.

import "github.com/rlaas-io/rlaas/pkg/rlaas"

client := rlaas.NewClient()
decision, err := client.Check(ctx, model.RequestContext{
    OrgID:      "acme",
    TenantID:   "retail",
    SignalType: "http",
    Operation:  "charge",
    Endpoint:   "/v1/charge",
    Method:     "POST",
    UserID:     "u1",
})

if decision.Allowed {
    // proceed
} else {
    // return 429 with decision.RetryAfter
}

For concurrency limiting:

decision, release, err := client.StartConcurrencyLease(ctx, req)
if decision.Allowed {
    defer release()
    // do heavy work
}
Python

Python SDK

Install: pip install rlaas-sdk (or install from sdk/python/)

from rlaas_sdk import RlaasClient, CheckRequest

client = RlaasClient("http://localhost:8080")

# Check decision
decision = client.check(CheckRequest(
    request_id="r1",
    org_id="acme",
    tenant_id="retail",
    signal_type="http",
    operation="charge",
    endpoint="/v1/charge",
    method="POST",
    user_id="u1"
))

print(f"Allowed: {decision.allowed}, Remaining: {decision.remaining}")

# Create policy
client.create_policy({
    "policy_id": "test-limit",
    "name": "Test Limit",
    "enabled": True,
    "scope": {"org_id": "acme", "signal_type": "http"},
    "algorithm": {"type": "fixed_window", "limit": 100, "window": "1m"},
    "action": "deny",
    "rollout_percent": 100
})

# Get audit trail
audit = client.get_audit("test-limit")

# Analytics
summary = client.get_analytics_summary(top=5)
TypeScript

TypeScript SDK

Install: npm install @rlaas/sdk (or import from sdk/typescript/)

import { RlaasClient } from '@rlaas/sdk';

const client = new RlaasClient('http://localhost:8080');

// Check decision
const decision = await client.check({
  request_id: 'r1',
  org_id: 'acme',
  tenant_id: 'retail',
  signal_type: 'http',
  operation: 'charge',
  endpoint: '/v1/charge',
  method: 'POST',
  user_id: 'u1',
});

console.log(`Allowed: ${decision.allowed}, Remaining: ${decision.remaining}`);

// List policies
const policies = await client.listPolicies();

// Rollout update
await client.rollout('payments-limit', 50);

// Rollback
await client.rollback('payments-limit', 1);
Node.js

Node.js SDK

Zero-dependency pure JavaScript client — no build step, no TypeScript compiler. Works with require() and import. Node 16+.

Install: npm install @rlaas/node-sdk (or reference sdk/nodejs/)

const { RlaasClient } = require('@rlaas/node-sdk');

const client = new RlaasClient('http://localhost:8080');

const decision = await client.check({
  request_id:  'r1',
  org_id:      'acme',
  tenant_id:   'retail',
  signal_type: 'http',
  endpoint:    '/v1/charge',
  method:      'POST',
  user_id:     'u1',
});

if (decision.allowed) {
  console.log(`allowed — ${decision.remaining} remaining`);
} else {
  res.status(429).json({ error: 'rate_limited', retry_after: decision.retry_after });
}

Express middleware:

const { rlaasExpress } = require('@rlaas/node-sdk/middleware');

app.use(rlaasExpress(client, (req) => ({
  org_id:      req.headers['x-org-id'] ?? 'default',
  signal_type: 'http',
  endpoint:    req.path,
  method:      req.method,
  user_id:     req.user?.id,
})));
// Returns 429 automatically when rate limited; passes through on allow.

Fastify hook:

const { rlaasPreHandler } = require('@rlaas/node-sdk/middleware');

fastify.addHook('preHandler', rlaasPreHandler(client, (req) => ({
  org_id:      req.headers['x-org-id'],
  signal_type: 'http',
  endpoint:    req.url,
  method:      req.method,
})));
Java

Java SDK

Add dependency from sdk/java/ (Maven, Java 11+).

import io.rlaas.sdk.RlaasClient;
import io.rlaas.sdk.model.CheckRequest;
import io.rlaas.sdk.model.Decision;

RlaasClient client = new RlaasClient("http://localhost:8080");

// Check decision
CheckRequest req = new CheckRequest();
req.setRequestId("r1");
req.setOrgId("acme");
req.setSignalType("http");
req.setOperation("charge");
req.setUserId("u1");

Decision decision = client.check(req);
System.out.println("Allowed: " + decision.isAllowed());
System.out.println("Remaining: " + decision.getRemaining());

// Create policy
String policyJson = """
  {
    "policy_id": "java-limit",
    "name": "Java Test",
    "enabled": true,
    "scope": {"org_id": "acme", "signal_type": "http"},
    "algorithm": {"type": "token_bucket", "limit": 200, "window": "1m", "burst": 50},
    "action": "deny",
    "rollout_percent": 100
  }
  """;
client.createPolicy(policyJson);
.NET

.NET SDK

Add project reference from sdk/dotnet/ (.NET 8).

using Rlaas.Sdk;

var client = new RlaasClient("http://localhost:8080");

// Check decision
var decision = await client.CheckAsync(new CheckRequest
{
    RequestId  = "r1",
    OrgId      = "acme",
    TenantId   = "retail",
    SignalType = "http",
    Operation  = "charge",
    Endpoint   = "/v1/charge",
    Method     = "POST",
    UserId     = "u1"
});

Console.WriteLine($"Allowed: {decision.Allowed}, Remaining: {decision.Remaining}");

// Policy management
var policies = await client.ListPoliciesAsync();
await client.RolloutAsync("payments-limit", 50);
await client.RollbackAsync("payments-limit", 1);

// Analytics
var summary = await client.GetAnalyticsSummaryAsync(top: 5);
C++

C++ SDK

Add via CMake using FetchContent or copy sdk/cpp/ into your project. Requires libcurl and nlohmann/json.

# CMakeLists.txt
include(FetchContent)
FetchContent_Declare(rlaas_sdk GIT_REPOSITORY https://github.com/rlaas-io/rlaas
                                GIT_TAG        main SOURCE_SUBDIR sdk/cpp)
FetchContent_MakeAvailable(rlaas_sdk)
target_link_libraries(my_app PRIVATE rlaas::sdk)
#include "rlaas/client.h"

int main() {
    rlaas::Client client("http://localhost:8080");

    // Check decision
    rlaas::CheckRequest req;
    req.request_id  = "r1";
    req.org_id      = "acme";
    req.tenant_id   = "retail";
    req.signal_type = "http";
    req.operation   = "charge";
    req.endpoint    = "/v1/charge";
    req.method      = "POST";
    req.user_id     = "u1";

    auto decision = client.check(req);
    if (decision.allowed) {
        // proceed
    } else {
        // return 429 — decision.retry_after_ms gives the backoff hint
    }

    // Create policy
    std::string policy_json = R"({
        "policy_id": "cpp-limit",
        "name": "C++ Service Limit",
        "enabled": true,
        "scope": {"org_id": "acme", "signal_type": "http"},
        "algorithm": {"type": "token_bucket", "limit": 500, "window": "1m", "burst": 100},
        "action": "deny",
        "rollout_percent": 100
    })";
    client.create_policy(policy_json);

    // List policies
    auto policies = client.list_policies();
    for (const auto& p : policies) {
        std::cout << p.policy_id << " — enabled: " << p.enabled << "\n";
    }
}

The C++ SDK is header-friendly and has no mandatory runtime dependencies beyond libcurl. Thread-safe for concurrent check() calls sharing one Client instance.

Rust

Rust SDK

Add to Cargo.toml (or reference the workspace crate from sdk/rust/):

[dependencies]
rlaas-sdk = { path = "sdk/rust" }
tokio = { version = "1", features = ["full"] }
serde_json = "1"
use rlaas_sdk::{Client, CheckRequest};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Client::new("http://localhost:8080");

    // Check decision
    let req = CheckRequest {
        request_id:  "r1".into(),
        org_id:      "acme".into(),
        tenant_id:   "retail".into(),
        signal_type: "http".into(),
        operation:   "charge".into(),
        endpoint:    "/v1/charge".into(),
        method:      "POST".into(),
        user_id:     "u1".into(),
        ..Default::default()
    };

    let decision = client.check(&req).await?;
    if decision.allowed {
        // proceed
    } else {
        eprintln!("rate limited — retry after {}ms", decision.retry_after_ms);
    }

    // Policy management
    let policies = client.list_policies().await?;
    println!("policies: {}", policies.len());

    client.rollout("payments-limit", 50).await?;
    client.rollback("payments-limit", 1).await?;

    // Analytics
    let summary = client.analytics_summary(5).await?;
    println!("top policy: {}", summary.top[0].policy_id);

    Ok(())
}

The Rust SDK uses reqwest with connection pooling and is fully async (tokio). All types implement Serialize / Deserialize so you can forward decisions into your own telemetry pipeline.

Ruby

Ruby SDK

Install: gem install rlaas-sdk (or add to Gemfile from sdk/ruby/):

# Gemfile
gem 'rlaas-sdk', path: 'sdk/ruby'
require 'rlaas_sdk'

client = Rlaas::Client.new('http://localhost:8080')

# Check decision
decision = client.check(
  request_id:  'r1',
  org_id:      'acme',
  tenant_id:   'retail',
  signal_type: 'http',
  operation:   'charge',
  endpoint:    '/v1/charge',
  method:      'POST',
  user_id:     'u1'
)

puts "Allowed: #{decision.allowed}, Remaining: #{decision.remaining}"

# Create policy
client.create_policy(
  policy_id:       'ruby-limit',
  name:            'Ruby Service Limit',
  enabled:         true,
  scope:           { org_id: 'acme', signal_type: 'http' },
  algorithm:       { type: 'sliding_window', limit: 200, window: '1m' },
  action:          'deny',
  rollout_percent: 100
)

# Get audit trail
audit = client.audit('ruby-limit')

# Analytics
summary = client.analytics_summary(top: 5)

Rails middleware integration:

# config/initializers/rlaas.rb
RLAAS = Rlaas::Client.new(ENV.fetch('RLAAS_URL', 'http://localhost:8080'))

# app/controllers/application_controller.rb
before_action :enforce_rate_limit

def enforce_rate_limit
  decision = RLAAS.check(
    org_id:      current_org.id,
    signal_type: 'http',
    endpoint:    request.path,
    method:      request.method,
    user_id:     current_user&.id
  )
  render json: { error: 'rate_limited' }, status: 429 unless decision.allowed
end

Common Patterns

Error Handling

All SDKs raise/throw on HTTP errors. Wrap calls in try/catch for production use:

try:
    decision = client.check(req)
except Exception as e:
    # fail open: allow on error
    print(f"RLAAS error: {e}, failing open")
try {
  const d = await client.check(req);
} catch (err) {
  console.warn('RLAAS error, failing open:', err);
}
try {
    Decision d = client.check(req);
} catch (Exception e) {
    System.err.println("RLAAS error, failing open: " + e.getMessage());
}
try {
    var d = await client.CheckAsync(req);
} catch (Exception ex) {
    Console.Error.WriteLine($"RLAAS error: {ex.Message}");
}
const { RlaasError } = require('@rlaas/node-sdk');

try {
  const d = await client.check(req);
} catch (err) {
  if (err instanceof RlaasError) {
    console.warn(`RLAAS ${err.statusCode}: ${err.message}, failing open`);
  }
  // fail open — allow the request through
}
try {
    auto d = client.check(req);
} catch (const rlaas::RlaasException& e) {
    // fail open: log and allow
    std::cerr << "RLAAS error, failing open: " << e.what() << "\n";
}
match client.check(&req).await {
    Ok(d) => { /* use d.allowed */ }
    Err(e) => {
        // fail open: log and allow
        eprintln!("RLAAS error, failing open: {e}");
    }
}
begin
  decision = client.check(req)
rescue Rlaas::Error => e
  # fail open: allow on error
  Rails.logger.warn "RLAAS error, failing open: #{e.message}"
  return
end

Custom Base URL

All SDKs accept a base URL in the constructor. Point to your production RLAAS server or local sidecar:

# Production
client = RlaasClient("https://rlaas.internal.company.com")

# Local sidecar
client = RlaasClient("http://localhost:18080")