sgcWebSockets 2026.5 — Rate Limiter, Circuit Breaker, API Keys, MCP OAuth & Faster IOCP

· Releases

sgcWebSockets 2026.5 is a meaty release. Three new infrastructure components turn the WebSocket / HTTP server into a production-grade API gateway: a fully-featured rate limiter, a client-side circuit breaker, and an API key manager with full lifecycle support. On the protocol side there is a new Forex.com client built on a generic Lightstreamer TLCP 2.5 implementation, the MCP Server gains a built-in OAuth 2.1 flow so it can connect directly to browser-based MCP clients such as claude.ai, and the IOCP (Windows) and EPOLL (Linux) I/O engines pick up six measurable performance wins. There is also an early post-quantum primitive: sgcKEM_CreateMLKEM768Keys for ML-KEM-768 keypair generation.

This post walks through the highlights with paste-ready Delphi snippets for the new components.

TsgcWSRateLimiter — drop-in API rate limiting

Drop a TsgcWSRateLimiter next to your server and you have token-bucket, sliding-window or fixed-window rate limiting per IP, per API key, per user or per endpoint pattern, plus daily/monthly quotas and burst protection. The component is thread-safe and persists state to disk (so a server restart does not give every client a fresh allowance).

uses
  sgcWebSocket_Server_RateLimiter;

var
  oRL: TsgcWSRateLimiter;
  oResult: TsgcRateLimitResult;
begin
  oRL := TsgcWSRateLimiter.Create(nil);
  try
    oRL.TokenBucket.Enabled    := True;
    oRL.TokenBucket.Capacity   := 100;     // burst size
    oRL.TokenBucket.RefillRate := 10;      // tokens / interval
    oRL.TokenBucket.RefillIntervalMs := 1000;

    oRL.PerIP.Enabled       := True;
    oRL.PerIP.MaxRequests   := 60;
    oRL.PerIP.WindowSec     := 60;

    // Consume one token for the current request
    oResult := oRL.Consume('ip:' + vClientIP);
    if not oResult.Allowed then
      RespondHTTP(429, 'Retry-After: ' + IntToStr(oResult.RetryAfterSec));
  finally
    oRL.Free;
  end;
end;

The rule resolver walks PerEndpoint (wildcard-matched), then PerAPIKey, PerUser, and finally PerIP. The OnThrottled, OnQuotaExceeded and OnStateChange events let you log or override every decision.

Demo: Demos\04.WebSocket_Other_Samples\14.RateLimiter — runs a flood-generating client against a server that publishes live stats and reject reasons.

TsgcWSCircuitBreaker — client-side fault isolation

When an upstream API (api.openai.com, a payments gateway, an internal microservice) starts failing or going slow, hanging on TCP timeouts costs you connections, threads and money. TsgcWSCircuitBreaker implements the classic three-state pattern (closed / open / half-open) on top of any TsgcHTTPAPI_client subclass, with a rolling time window, slow-call detection, optional fallback responses, and per-endpoint overrides.

uses
  sgcWebSocket_CircuitBreaker;

var
  oCB: TsgcWSCircuitBreaker;
begin
  oCB := TsgcWSCircuitBreaker.Create(nil);
  try
    oCB.Thresholds.FailureCount        := 5;
    oCB.Thresholds.FailureRatePercent  := 50;
    oCB.Thresholds.SlowCallDurationMs  := 2000;
    oCB.Thresholds.SlowCallRatePercent := 80;
    oCB.TimeWindow.RollingWindowSec    := 60;
    oCB.Recovery.CooldownSec           := 30;
    oCB.Recovery.HalfOpenTrialCalls    := 3;

    oCB.Fallback.Enabled        := True;
    oCB.Fallback.UseLastSuccess := True;

    if oCB.IsCallAllowed('openai') then
    try
      vResponse := oOpenAI.ChatCompletion(...);
      oCB.RecordSuccess('openai');
    except
      on E: Exception do
      begin
        oCB.RecordFailure('openai', E.ClassName);
        raise;
      end;
    end
    else
      vResponse := 'service temporarily unavailable';
  finally
    oCB.Free;
  end;
end;

On Delphi 2009+ a one-liner wrapper is also available: oCB.Execute('openai', procedure begin oOpenAI.ChatCompletion(...) end); — success / failure recording happens automatically.

Demo: Demos\04.WebSocket_Other_Samples\15.CircuitBreaker.

TsgcWSAPIKeyManager — key lifecycle in one component

Most "WebSocket API" servers need API keys: issue, validate, revoke, rotate. TsgcWSAPIKeyManager wraps the full lifecycle with scope-based authorisation, optional hashing at rest, expiration, an audit log, and a built-in rotation grace period so old keys keep working for a configurable window after rotation.

uses
  sgcWebSocket_Server_APIKeyManager;

var
  oKM: TsgcWSAPIKeyManager;
  vKey, vNewKey: string;
begin
  oKM := TsgcWSAPIKeyManager.Create(nil);
  try
    oKM.Generation.Length := 40;
    oKM.Generation.Prefix := 'sgc_';
    oKM.Hashing.Enabled   := True;        // store SHA-256 hash, not the plaintext
    oKM.Rotation.GracePeriodSec := 86400; // old key valid for 24h after rotation
    oKM.Expiration.DefaultTTLSec := 30 * 86400;

    // Issue a key for tenant "acme" with read+write scopes, expiring in 7 days
    vKey := oKM.IssueKey('acme', ['read', 'write'], 7 * 86400);

    // Validate the key on each request, optionally requiring a scope
    if not oKM.ValidateKey(vKey, 'read', vClientIP) then
      RespondHTTP(401, 'invalid api key');

    // Rotate a key (returns the new plaintext; old key remains valid for GracePeriodSec)
    oKM.RotateKey(vKey, vNewKey);
  finally
    oKM.Free;
  end;
end;

The component can read the key directly out of the inbound HTTP headers or query string with IsRequestAuthorized, so you do not have to wire the extraction yourself.

Demo: Demos\04.WebSocket_Other_Samples\16.APIKeyManager.

Forex.com client + generic Lightstreamer

The new TsgcWSAPI_Forex client offers unified REST + streaming access to Forex.com (login, ping, market watch, positions, orders, trade history, simulate trade). It is built on a brand-new TsgcWSPClient_Lightstreamer component, a generic Lightstreamer TLCP 2.5 client that implements create_session, bind_session, control (subscribe / unsubscribe) and the LOOP auto-rebind + subscription replay after reconnect. The Lightstreamer client is reusable on its own, so the same code base works with IG Markets and any other Lightstreamer-backed feed.

uses sgcHTTP_API_Forex;

var oFX: TsgcWSAPI_Forex;
begin
  oFX := TsgcWSAPI_Forex.Create(nil);
  oFX.UserName  := 'demo-user';
  oFX.Password  := 'secret';
  oFX.AppKey    := 'your-app-key';
  oFX.Login;
  oFX.SubscribePrices(['EUR/USD', 'GBP/USD', 'XAU/USD']);
  oFX.OnPriceUpdate := procedure(const aSymbol: string; aBid, aAsk: Double)
                      begin
                        ShowMessage(Format('%s %.5f / %.5f', [aSymbol, aBid, aAsk]));
                      end;
end;

A full GUI demo lives in Demos\05.Crypto\22.Forex — login, connectivity ping, live market watch, positions, active orders, trade history, stop / limit history and simulate trade, with credentials persisted to sgcForexDemo.ini.

MCP Server — OAuth 2.1 for browser-based MCP clients

The MCP Server can now talk directly to browser-based MCP connectors (such as claude.ai) without an external authorisation server. It auto-publishes the four OAuth discovery / registration endpoints required by the MCP browser-connector spec, runs a PKCE-S256 authorisation flow with an HTML consent screen, and issues refresh tokens:

CORS is handled inline: OPTIONS preflight returns 204 with full Access-Control-* headers before authentication, every response carries an Access-Control-Allow-Origin reflection of the request origin and a Strict-Transport-Security: max-age=31536000 HSTS header.

IOCP and EPOLL: six tuning wins

The Windows IOCP and Linux EPOLL I/O engines got a focused round of performance and tunability work.

IOCP (Windows)

oServer.Bindings.Add.Port := 443;
oServer.IOHandler := TsgcIndy_IOHandler_IO_IOCP.Create(oServer);
with TsgcIndy_IOHandler_IO_IOCP(oServer.IOHandler) do
begin
  SendBufferSize    := 256 * 1024;
  ReceiveBufferSize := 256 * 1024;
  TCPNoDelay        := True;
  Engine.ThreadAffinity := True;
end;

EPOLL (Linux)

Shared

The IOCP / EPOLL worker pool used to sleep(1) on every iteration including right after a task was processed — effectively capping each worker at ~1,000 ops/s even when the queue was full. The sleep is now skipped while there is work waiting, removing the cap.

HTTP.sys: opt-in high-performance mode

The HTTP.sys server gains a FineTune property with an OperatingMode selector. The default ompClassic preserves the existing behaviour. The new ompHighPerf mode implements the MSDN N-workers × M-pre-posted-async-receives pattern — the recommended architecture for high-throughput HTTP.sys deployments — behind a single property:

oServer := TsgcWebSocketHTTPServer.Create(nil);
oServer.HTTP2Options.SecureOptions.HTTPAPI := True;   // use HTTP.sys
oServer.FineTune.OperatingMode := ompHighPerf;
oServer.FineTune.WorkerCount   := 8;
oServer.FineTune.PrePostedReceivesPerWorker := 16;
oServer.Active := True;

THttpServerRequest and THttpServerResponse have also been extended with additional fields covering details previously only available through manual parsing.

Post-quantum primitive: ML-KEM-768

A small but forward-looking addition: sgcKEM_CreateMLKEM768Keys generates an ML-KEM-768 (FIPS 203 / Kyber-768) keypair in both PEM and raw-bytes form. ML-KEM is the post-quantum KEM standardised by NIST and on the IETF roadmap for hybrid TLS 1.3 (X25519MLKEM768). This unblocks experimenting with PQ-ready handshakes ahead of the upcoming OpenSSL 3.5 / 3.6 baseline.

uses sgcKEM;

var vPubPEM, vPrivPEM: string; vPubRaw, vPrivRaw: TBytes;
begin
  sgcKEM_CreateMLKEM768Keys(vPubPEM, vPrivPEM, vPubRaw, vPrivRaw);
  TFile.WriteAllText('mlkem768_pub.pem', vPubPEM);
  TFile.WriteAllText('mlkem768_priv.pem', vPrivPEM);
end;

Reliability and conformance fixes

The bug-fix batch closes a long list of MCP, HTTP.sys, IOCP and HTTP/2 issues. Highlights:

Upgrading

2026.5 is a drop-in upgrade for existing 2026.4 projects. No interface changes were made to existing components; the new rate-limit / circuit-breaker / API-key components are additive and opt-in. The HTTP.sys high-performance mode is gated behind FineTune.OperatingMode := ompHighPerf — existing code stays on the classic path.

Customers with an active subscription can download the new build from the customer area. Trial users can grab the updated installer at esegece.com/products/sgcwebsockets/sgcwebsockets-download.

Questions, feedback or migration help? Get in touch — you will get a reply from the people who wrote the code.