Soasap.Sdk
SOASAP .NET SDK
Lightweight, production-ready feature flags SDK for .NET — lock-free O(1) reads, zero network calls on startup, real-time SSE updates, persistent disk cache, and graceful offline behavior. ASP.NET Core, Worker Services, Console Apps, Blazor.
Installation
Install from NuGet. Supports .NET 6, .NET 8, .NET 9, .NET 10, and .NET Standard 2.0.
dotnet add package Soasap.Sdk
Quick start
Register with AddSoasap(), call
PreloadFlags() for non-blocking startup sync,
and inject ISOASAPClient anywhere in your app.
using Soasap.Sdk;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSoasap("your-api-key")
.PreloadFlags();
var app = builder.Build();
app.Run();
Use feature flags
Evaluate flags on the hot path with zero network I/O. Getters never throw — safe for production request paths.
app.MapGet("/", (ISOASAPClient flags) =>
{
if (flags.GetBool("new-checkout"))
return "New checkout enabled";
return "Old checkout";
});
Typed access
Bool, number, string, and JSON remote config.
JSON deserialization is case-insensitive (camelCase → PascalCase).
var enabled = flags.GetBool("feature-x");
var limit = flags.GetNumber("rate-limit", 100);
var theme = flags.GetString("ui-theme", "light");
var config = flags.GetJson<CheckoutConfig>("checkout-config");
Startup sync
PreloadFlags() (recommended) starts the SSE worker via
IHostedService, loads the disk cache on cold start, and never blocks host startup.
Without it, lazy mode defers the network connection until the first flag evaluation.
In lazy mode, no background workers start at boot. The first evaluation uses default values (or the local disk cache if available) while the SSE stream connects in the background.
// Immediate sync (recommended)
builder.Services.AddSoasap("your-api-key")
.PreloadFlags();
// Lazy sync — first read falls back to defaults or disk cache
builder.Services.AddSoasap("your-api-key");
Error handling & observability
Hook background diagnostics without affecting the hot path.
Sources: Network, Disk, Parser.
builder.Services.AddSoasap("your-api-key")
.OnError(ctx =>
{
Console.WriteLine(
$"[{ctx.Source}] (Transient: {ctx.IsTransient}) " +
$"-> {ctx.Exception.Message}");
});
public enum SoasapErrorSource
{
Network,
Disk,
Parser
}
Production safety & guardrails
- No race conditions — atomic lock-free immutable snapshot replacement; no partial mutation or
ObjectDisposedException - Memory cap protection (anti-DoS) — 5 MB SSE payload cap; oversized streams are dropped and reset
- Payload validation — root element must be a JSON object
{}; invalid payloads are ignored - IO coalescing (disk debounce) — disk writes coalesced at most once every 2–3 seconds
- Thread safety —
ISOASAPClientis a thread-safe singleton
The SDK never throws from flag getters.
Offline resiliency
| Scenario | Behavior |
|---|---|
| API unavailable | Uses stale cached flags |
| SSE disconnected | Keeps last known snapshot |
| First startup without cache | Returns default values |
| Invalid payload | Payload ignored |
| Disk cache failure | In-memory mode continues |
| Persistent network issues | Reconnect with backoff |
Disk cache: %LocalAppData%\soasap\cache (Windows),
~/.local/share/soasap/cache (Linux/macOS).
Override with .WithCacheDirectory("/custom/path").
Supported frameworks
- .NET 6 / .NET 8 / .NET 9 / .NET 10
- .NET Standard 2.0 (compatible with legacy .NET Framework apps)