Superposition, a Context Aware Configuration Management System
Facilitate safe & flexible rollout of config changes with granular configuration based on contextual data, A/B testing, controlled rollout and rollback mechanisms
        
          
[default-config]
per_km_rate = { "value" = 20.0, "schema" = { "type" = "number" } }
surge_factor = { "value" = 0.0, "schema" = { "type" = "number" } }
[dimensions]
city = { schema = { "type" = "string", "enum" = ["Bangalore", "Delhi"] }}
vehicle_type = { schema = { "type" = "string", "enum" = ["auto", "cab", "bike"] }}
hour_of_day = { schema = { "type" = "integer", "minimum" = 0, "maximum" = 23 }}
[context."$vehicle_type == 'cab'"]
per_km_rate = 25.0
[context."$vehicle_type == 'bike'"]
per_km_rate = 15.0
[context."$city == 'Bangalore' && $vehicle_type == 'auto'"]
per_km_rate = 22.0
[context."$city == 'Delhi' && $hour_of_day >= 12 && $hour_of_day <= 18"]
surge_factor = 5.0
        
      Typed
Enforces strict type safety and custom validation functions, preventing incorrect configuration values from being stored.
Experiments
Supports multi-variate experiments for data driven decision making and safe config releases.
Multi-tenant
Multi-tenant ready, allowing multiple teams within an organization to manage configurations with isolation in a single instance.
UI-Support
Out of the box powerful UI to perform all configuration management activities
Rich API
All Superposition actions are backed by API end-points, enabling teams programmatic configuration changes
Performant Client
Completely in memory lookups for config with a performant async client. Clients available in Java, Python, Javascript, Go, Rust, Haskell and more...
                
                  
use cac_client;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let client = cac_client::CLIENT_FACTORY
        .create_client(
            "dev".to_string(),
            std::time::Duration::new(10, 0),
            "http://localhost:8080".into(),
        )
        .await
        .unwrap();
    actix_web::rt::spawn(client.clone().run_polling_updates());
    let resolved_config = client
        .get_resolved_config(
            serde_json::json!({"country": "india"})
                .as_object()
                .unwrap()
                .clone(),
            None,
            cac_client::MergeStrategy::MERGE,
        )
        .await
        .unwrap();
    println!("{resolved_config:?}");
    Ok(())
}
                
                              
                  
module Main (main) where
import           Client             as CAC
import           Control.Concurrent
import           Prelude
main :: IO ()
main = do
  CAC.createCacClient "dev" 10 "http://localhost:8080" >>= case
    Left err -> putStrLn err
    Right _  -> pure ()
  threadId <- forkOS (CAC.cacStartPolling "dev")
  CAC.getCacClient "dev" >>= case
    Left err     -> putStrLn err
    Right client -> do
      resolvedConfig  <- CAC.getResolvedConfig
                           client
                           "{"country": "India"}" $
                           Nothing
  pure ()
                
                              
                  
package main
import (
	"fmt"
	"github.com/juspay/superposition/clients/go/cacclient"
)
func main() {
	tenant := "dev"
	pollingFrequency := 1
	cacHostName := 
	client, error := cacclient.NewCacClient(tenant, pollingFrequency, cacHostName)
	if error != nil {
		fmt.Println(error)
	}
	fmt.Println("Resolved Config => ", client.GetResolvedConfig(map[string]string{"country": "india"}, nil, cacclient.MERGE))
}
                
                              
                  
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import cac_client.CacClient;
import jnr.ffi.Pointer;
public class Application {
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(1);
        try {
            CacClient client = new CacClient();
            int newClient = client.cacNewClient(tenant, 1, "http://localhost:8080");
            Thread pollingThread = new Thread(() -> {
                client.startPollingUpdate(tenant);
            });
            Pointer clientPtr = client.getCacClient(tenant);
            String resolvedConfig = client.getResolvedConfig(clientPtr, "{"clientId": "abcd"}", null, "MERGE");
            System.out.println("Resolved Config: " + resolvedConfig);
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }
    }
}
                
                              
                  
import {CacReader} from "superposition/clients/js/index.js";
import config from "./config.json";
const Cac = new CacReader(config);
const resolvedConfig = Cac.evaluateConfig({"country": "india"});
                
                              
                  
import {CacClient, MergeStrategy} from 'cac_client';
let tenantName: string = "dev";
let superpositionHost: string = "http://localhost:8080";
let pollingFrequency: number = 1;
let CACClient = new CacClient(tenantName, pollingFrequency, superpositionHost);
CACClient.startPollingUpdate();
let resolvedConfig = CACClient.getResolvedConfig({"country" : "india"}, undefined, MergeStrategy.MERGE);
console.log(resolvedConfig);
                
                              
                  
from cacclient import CacClient , MergeStrategy
def main():
    tenant_name = "dev"
    polling_frequency = 1
    cac_host_name = "http://localhost:8080"
    cac_client = CacClient(tenant_name, polling_frequency, cac_host_name)
    cac_client.start_cac_polling_update()
    resolved_config = cac_client.get_resolved_config(dict({'country': 'India'}), MergeStrategy.MERGE)
    print(resolved_config)
if __name__=="__main__":
    main()
                
              
 
 
 

