# Superposition Superposition is a configuration and experimentation management platform built in Rust that enables software teams to manage their configurations safely while running multi-variate experiments. The platform provides context-aware configuration (CAC) where configuration values can be overridden based on dimensional contexts like geographic regions, user segments, or time-of-day, similar to how CSS selectors work. It emphasizes safety through strong typing via JSON Schema validation, custom JavaScript validation functions, and gradual rollouts through experiments. The platform is designed as a multi-tenant system with organizations and workspaces for isolation. It offers an Admin UI for managing configurations, comprehensive REST APIs, and client SDKs for Rust, JavaScript, Python, Java, and Haskell. Superposition is OpenFeature-compatible, allowing applications to remain agnostic of the underlying configuration platform while consuming configurations through standardized feature flag interfaces. ## Getting Started Run Superposition using Docker to expose the admin interface at port 8080. ```bash # Start Superposition demo with pre-populated data docker run -p 8080:8080 ghcr.io/juspay/superposition-demo:latest # For production deployments docker run -p 8080:8080 ghcr.io/juspay/superposition:latest ``` ## Configuration Management APIs ### Get Resolved Configuration Resolves and merges configuration values based on context conditions, applying overrides and merge strategies to produce the final configuration for an application. ```bash # Get resolved configuration for a specific context curl -X POST 'http://localhost:8080/config/resolve' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "city": "Delhi", "vehicle_type": "cab", "hour_of_day": 19 } }' # Response: # { # "per_km_rate": 25.0, # "surge_factor": 5.0 # } # Get config with prefix filter and reasoning curl -X POST 'http://localhost:8080/config/resolve?prefix=payment&show_reasoning=true' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "region": "north", "user_type": "premium" } }' ``` ### Get Configuration Fast Retrieves the latest configuration without processing for high-performance access when context evaluation is not needed. ```bash # Get full configuration without context evaluation curl -X GET 'http://localhost:8080/config/fast' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' # Response includes all contexts, overrides, and default values # Headers include: last-modified, x-config-version ``` ### Get Full Configuration with Context Retrieves complete configuration data including applicable contexts, overrides, and default values based on provided conditions. ```bash curl -X POST 'http://localhost:8080/config' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "city": "Bangalore", "vehicle_type": "cab" } }' # Response structure includes: # - contexts: array of matching context objects # - overrides: key-value overrides applied # - default_configs: fallback values ``` ## Default Configuration APIs ### Create Default Configuration Creates a new default configuration entry with a specified key, value, JSON Schema, and optional validation function. ```bash curl -X POST 'http://localhost:8080/default-config' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "key": "per_km_rate", "value": 20.0, "schema": { "type": "number", "minimum": 0 }, "description": "Base rate per kilometer for rides", "change_reason": "Initial configuration setup" }' # Create config with complex schema curl -X POST 'http://localhost:8080/default-config' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "key": "payment_config", "value": { "enabled": true, "methods": ["card", "upi", "wallet"] }, "schema": { "type": "object", "properties": { "enabled": { "type": "boolean" }, "methods": { "type": "array", "items": { "type": "string" } } }, "required": ["enabled", "methods"] } }' ``` ### Update Default Configuration Updates an existing default configuration entry while preserving the key identifier. ```bash curl -X PATCH 'http://localhost:8080/default-config/per_km_rate' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "value": 22.0, "schema": { "type": "number", "minimum": 0, "maximum": 100 }, "change_reason": "Updated base rate for inflation" }' ``` ### List and Get Default Configurations Retrieves default configuration entries with pagination support. ```bash # List all default configs with pagination curl -X GET 'http://localhost:8080/default-config?page=1&count=10' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' # Get specific default config by key curl -X GET 'http://localhost:8080/default-config/per_km_rate' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' # Get all default configs (no pagination) curl -X GET 'http://localhost:8080/default-config?all=true' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' ``` ## Dimension APIs ### Create Dimension Creates a new dimension that defines categorical attributes used for context-based configuration management. ```bash # Create a simple enum dimension curl -X POST 'http://localhost:8080/dimension' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "dimension": "city", "schema": { "type": "string", "enum": ["Bangalore", "Delhi", "Mumbai", "Chennai"] }, "description": "City where the service is operating", "change_reason": "Adding city dimension for regional config" }' # Create dimension with dependencies curl -X POST 'http://localhost:8080/dimension' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "dimension": "zone", "schema": { "type": "string" }, "dependencies": ["city"], "description": "Zone within a city" }' # Create numeric range dimension curl -X POST 'http://localhost:8080/dimension' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "dimension": "hour_of_day", "schema": { "type": "integer", "minimum": 0, "maximum": 23 } }' ``` ### Update and Delete Dimensions Modifies or removes dimensions from the workspace. ```bash # Update dimension schema curl -X PATCH 'http://localhost:8080/dimension/city' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "schema": { "type": "string", "enum": ["Bangalore", "Delhi", "Mumbai", "Chennai", "Hyderabad"] }, "change_reason": "Added Hyderabad to supported cities" }' # Delete dimension (fails if referenced by contexts) curl -X DELETE 'http://localhost:8080/dimension/zone' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' ``` ## Context APIs ### Create Context with Overrides Creates a new context with specified conditions and configuration overrides that apply when the condition is met. ```bash # Create context with simple condition curl -X PUT 'http://localhost:8080/context' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "==": [{ "var": "vehicle_type" }, "cab"] }, "override": { "per_km_rate": 25.0 }, "description": "Rate override for cab rides", "change_reason": "Setting cab-specific pricing" }' # Create context with compound conditions (AND) curl -X PUT 'http://localhost:8080/context' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "and": [ { "==": [{ "var": "city" }, "Delhi"] }, { "==": [{ "var": "vehicle_type" }, "cab"] }, { ">=": [{ "var": "hour_of_day" }, 18] } ] }, "override": { "surge_factor": 5.0, "per_km_rate": 30.0 }, "description": "Evening surge pricing in Delhi for cabs" }' # Create context with OR condition curl -X PUT 'http://localhost:8080/context' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "or": [ { "==": [{ "var": "city" }, "Mumbai"] }, { "==": [{ "var": "city" }, "Bangalore"] } ] }, "override": { "metro_city_discount": true } }' ``` ### Update Context Overrides Updates the overrides for an existing context while maintaining its conditions. ```bash curl -X PATCH 'http://localhost:8080/context/overrides' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "==": [{ "var": "vehicle_type" }, "cab"] }, "override": { "per_km_rate": 28.0, "booking_fee": 5.0 }, "change_reason": "Updated cab pricing structure" }' ``` ### Bulk Context Operations Executes multiple context operations in a single atomic transaction. ```bash curl -X PUT 'http://localhost:8080/context/bulk-operations' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "operations": [ { "PUT": { "context": { "==": [{ "var": "vehicle_type" }, "bike"] }, "override": { "per_km_rate": 15.0 } } }, { "PUT": { "context": { "==": [{ "var": "vehicle_type" }, "auto"] }, "override": { "per_km_rate": 18.0 } } }, { "DELETE": { "context_id": "old-context-id-to-remove" } } ] }' ``` ## Experimentation APIs ### Create Experiment Creates a new A/B experiment with control and experimental variants for testing configuration changes. ```bash curl -X POST 'http://localhost:8080/experiments' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "name": "checkout-optimization", "context": { "and": [ { "==": [{ "var": "region" }, "north"] }, { "==": [{ "var": "user_type" }, "premium"] } ] }, "variants": [ { "id": "control", "variant_type": "CONTROL", "overrides": { "checkout_button_color": "blue", "show_discount_banner": false } }, { "id": "treatment-a", "variant_type": "EXPERIMENTAL", "overrides": { "checkout_button_color": "green", "show_discount_banner": true } } ], "description": "Testing new checkout UI for premium users" }' ``` ### Ramp Experiment Traffic Adjusts the traffic percentage for an experiment to gradually roll out changes. ```bash # Start experiment with 10% traffic curl -X PATCH 'http://localhost:8080/experiments/123456/ramp' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "traffic_percentage": 10, "change_reason": "Initial rollout to 10% of users" }' # Increase to 50% traffic curl -X PATCH 'http://localhost:8080/experiments/123456/ramp' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "traffic_percentage": 50, "change_reason": "Scaling up after positive initial results" }' ``` ### Conclude Experiment Concludes an experiment by selecting a winning variant and applying its configuration. ```bash curl -X PATCH 'http://localhost:8080/experiments/123456/conclude' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "chosen_variant": "treatment-a", "change_reason": "Treatment A showed 15% conversion improvement" }' ``` ### Get Applicable Variants Determines which experiment variants apply to a given context for client-side variant assignment. ```bash curl -X POST 'http://localhost:8080/experiments/applicable-variants' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "context": { "region": "north", "user_type": "premium", "user_id": "user-12345" }, "toss": 42 }' # Response: # { # "applicable_variants": ["treatment-a"], # "experiment_id": 123456 # } ``` ## OpenFeature Provider Integration ### JavaScript/TypeScript Setup Initialize the Superposition OpenFeature provider for feature flag evaluation in Node.js applications. ```javascript import { OpenFeature } from '@openfeature/server-sdk'; import { SuperpositionProvider } from 'superposition-provider'; // Configure provider const config = { endpoint: "http://localhost:8080", token: "api-token", org_id: "localorg", workspace_id: "test", refresh_strategy: { type: "polling", interval: 5000, // Poll every 5 seconds timeout: 3000 // Timeout after 3 seconds } }; const provider = new SuperpositionProvider(config); await OpenFeature.setProviderAndWait(provider); // Get client and evaluate flags const client = OpenFeature.getClient(); const context = { city: "Bangalore", vehicle_type: "cab" }; // Boolean flag evaluation const isFeatureEnabled = await client.getBooleanValue("new_checkout_enabled", false, context); console.log("Feature enabled:", isFeatureEnabled); // String flag evaluation const buttonColor = await client.getStringValue("checkout_button_color", "blue", context); console.log("Button color:", buttonColor); // Number flag evaluation const discountPercent = await client.getNumberValue("discount_percentage", 0, context); console.log("Discount:", discountPercent); // Get entire resolved configuration const allConfig = await provider.resolveAllConfigDetails({}, context); console.log("Full config:", allConfig); ``` ### Python Setup Configure and use the Superposition provider in Python applications. ```python import asyncio from openfeature import api from openfeature.evaluation_context import EvaluationContext from superposition_provider.provider import SuperpositionProvider from superposition_provider.types import ( SuperpositionProviderOptions, ExperimentationOptions, PollingStrategy ) async def main(): # Configure provider options options = SuperpositionProviderOptions( endpoint="http://localhost:8080", token="api-token", org_id="localorg", workspace_id="test", refresh_strategy=PollingStrategy( interval=5, # Poll every 5 seconds timeout=3 # Timeout after 3 seconds ), experimentation_options=ExperimentationOptions( refresh_strategy=PollingStrategy(interval=5, timeout=3) ) ) # Initialize provider provider = SuperpositionProvider(provider_options=options) ctx = EvaluationContext(attributes={"city": "Delhi", "vehicle_type": "cab"}) await provider.initialize(context=ctx) api.set_provider(provider) # Get client and evaluate flags client = api.get_client() # Evaluate boolean flag bool_result = client.get_boolean_details( flag_key="new_feature_enabled", default_value=False, evaluation_context=ctx ) print(f"Boolean flag: {bool_result.value}") # Evaluate number flag rate = client.get_number_details( flag_key="per_km_rate", default_value=20.0, evaluation_context=ctx ) print(f"Per km rate: {rate.value}") # Get all resolved config all_config = provider.resolve_all_config_details({}, ctx) print(f"Full config: {all_config}") asyncio.run(main()) ``` ### Java/Kotlin Setup Initialize the Superposition provider in JVM-based applications. ```java import dev.openfeature.sdk.*; import io.juspay.superposition.openfeature.*; import io.juspay.superposition.openfeature.options.RefreshStrategy; import java.util.Map; public class SuperpositionExample { public static void main(String[] args) { // Configure experimentation options SuperpositionProviderOptions.ExperimentationOptions expOptions = SuperpositionProviderOptions.ExperimentationOptions.builder() .refreshStrategy(RefreshStrategy.Polling.of(5000, 2000)) .build(); // Configure provider options SuperpositionProviderOptions options = SuperpositionProviderOptions.builder() .orgId("localorg") .workspaceId("test") .endpoint("http://localhost:8080") .token("api-token") .refreshStrategy(RefreshStrategy.Polling.of(10000, 5000)) .experimentationOptions(expOptions) .build(); // Initialize provider SuperpositionOpenFeatureProvider provider = new SuperpositionOpenFeatureProvider(options); EvaluationContext initCtx = new ImmutableContext(Map.of("city", new Value("Bangalore"))); provider.initialize(initCtx); OpenFeatureAPI.getInstance().setProvider(provider); // Get client and evaluate flags Client client = OpenFeatureAPI.getInstance().getClient(); EvaluationContext ctx = new ImmutableContext(Map.of( "city", new Value("Delhi"), "vehicle_type", new Value("cab"), "hour_of_day", new Value(19) )); // Boolean evaluation boolean enabled = client.getBooleanValue("surge_pricing_enabled", false, ctx); System.out.println("Surge enabled: " + enabled); // Number evaluation double rate = client.getDoubleValue("per_km_rate", 20.0, ctx); System.out.println("Per km rate: " + rate); // Get full configuration System.out.println("Full config: " + provider.evaluateConfig(ctx)); } } ``` ### Rust Setup Configure the Superposition provider for Rust applications. ```rust use superposition_provider::{ SuperpositionProvider, SuperpositionProviderOptions, RefreshStrategy, PollingStrategy }; use open_feature::OpenFeature; use std::collections::HashMap; use tokio::time::{sleep, Duration}; #[tokio::main] async fn main() { env_logger::init(); // Get OpenFeature API singleton let mut api = OpenFeature::singleton_mut().await; // Configure provider let options = SuperpositionProviderOptions { endpoint: "http://localhost:8080/".to_string(), token: "api-token".to_string(), org_id: "localorg".to_string(), workspace_id: "test".to_string(), fallback_config: None, evaluation_cache: None, refresh_strategy: RefreshStrategy::Polling(PollingStrategy { interval: 60, timeout: Some(30) }), experimentation_options: None }; // Set provider api.set_provider(SuperpositionProvider::new(options)).await; // Create client let client = api.create_client(); sleep(Duration::from_secs(3)).await; // Build evaluation context let mut context = HashMap::new(); context.insert("city".to_string(), "Bangalore".into()); context.insert("vehicle_type".to_string(), "cab".into()); // Evaluate feature flags let rate = client .get_float_value("per_km_rate", Some(&context), None) .await .unwrap_or(20.0); println!("Per km rate: {}", rate); let enabled = client .get_bool_value("new_feature_enabled", Some(&context), None) .await .unwrap_or(false); println!("Feature enabled: {}", enabled); } ``` ## TOML Configuration Format ### Define Complete Configuration in TOML Superposition supports TOML format for defining configurations, dimensions, and context overrides declaratively. ```toml # Define default configuration values with schemas [default-config] per_km_rate = { "value" = 20.0, "schema" = { "type" = "number", "minimum" = 0 } } surge_factor = { "value" = 0.0, "schema" = { "type" = "number" } } booking_fee = { "value" = 5.0, "schema" = { "type" = "number" } } show_surge_warning = { "value" = false, "schema" = { "type" = "boolean" } } # Define dimensions with JSON Schema validation [dimensions] city = { schema = { "type" = "string", "enum" = ["Bangalore", "Delhi", "Mumbai"] } } vehicle_type = { schema = { "type" = "string", "enum" = ["auto", "cab", "bike"] } } hour_of_day = { schema = { "type" = "integer", "minimum" = 0, "maximum" = 23 } } user_tier = { schema = { "type" = "string", "enum" = ["bronze", "silver", "gold"] } } # Define context overrides using dimension expressions [context."$vehicle_type == 'cab'"] per_km_rate = 25.0 booking_fee = 10.0 [context."$vehicle_type == 'bike'"] per_km_rate = 15.0 booking_fee = 3.0 [context."$city == 'Bangalore' && $vehicle_type == 'cab'"] per_km_rate = 22.0 [context."$city == 'Delhi' && $vehicle_type == 'cab' && $hour_of_day >= 18"] surge_factor = 5.0 show_surge_warning = true [context."$city == 'Delhi' && $vehicle_type == 'cab' && $hour_of_day <= 6"] surge_factor = 3.0 show_surge_warning = true [context."$user_tier == 'gold'"] booking_fee = 0.0 ``` ## Webhook Configuration ### Create Experiment Webhooks Configure webhooks to receive notifications about experiment lifecycle events. ```bash # Create webhook for experiment events curl -X POST 'http://localhost:8080/webhook' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "name": "deployment-webhook", "description": "Triggers deployments based on experiment events", "enabled": true, "url": "https://your-service.com/webhook", "method": "POST", "events": ["ExperimentStarted", "ExperimentConcluded", "ExperimentInprogress"], "custom_headers": { "Authorization": "Bearer your-api-token", "Content-Type": "application/json" }, "max_retries": 3, "change_reason": "Setting up automated deployments" }' # Webhook handler example (Node.js) # app.post('/webhook', (req, res) => { # const { event_info, payload } = req.body; # # switch (event_info.webhook_event) { # case 'ExperimentStarted': # deployNewVariant(payload); # break; # case 'ExperimentConcluded': # promoteVariant(payload.chosen_variant); # break; # case 'ExperimentInprogress': # updateTrafficSplit(payload.traffic_percentage); # break; # } # # res.status(200).json({ message: 'Webhook processed' }); # }); ``` ## Functions and Validation ### Create Custom Validation Function Define JavaScript validation functions for custom business logic beyond JSON Schema. ```bash curl -X POST 'http://localhost:8080/function' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "function_name": "validate_city_code", "function": "async function validate(key, value) { const validCities = [\"BLR\", \"DEL\", \"MUM\"]; return validCities.includes(value) && value.length === 3; }", "runtime_version": "1", "description": "Validates city codes against approved list", "change_reason": "Adding city code validation" }' # Test the function curl -X POST 'http://localhost:8080/function/validate_city_code/test' \ -H 'Content-Type: application/json' \ -H 'x-org-id: localorg' \ -H 'x-workspace: test' \ -d '{ "key": "city_code", "value": "BLR" }' ``` ## Summary Superposition serves as a comprehensive platform for managing application configurations with context-aware overrides and safe experimentation capabilities. The primary use cases include gradual feature rollouts through A/B testing, regional configuration management where different geographic areas require different values, time-based configuration changes like surge pricing, and user segmentation where premium users receive different experiences. The platform's CSS-like cascading configuration model makes it intuitive to understand how configurations resolve from general defaults to specific contextual overrides. Integration follows a straightforward pattern: teams define dimensions representing their domain attributes, create default configurations with JSON Schema validation, set up context overrides with conditions using those dimensions, and optionally run experiments to test configuration changes safely. Client applications consume configurations through OpenFeature-compatible providers that handle caching and periodic polling for updates, ensuring applications always have current configurations while remaining decoupled from the underlying platform. The combination of strong typing, custom validation functions, multi-tenant isolation, and comprehensive audit logging makes Superposition suitable for enterprise environments requiring both flexibility and governance over configuration changes.