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

application.js
            
        
Context
Hour of the day
00:00
00:00
01:00
02:00
03:00
04:00
05:00
06:00
07:00
08:00
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00
Vehicle Type
Auto
Cab
Bike
City
Outcome
Delhi
(20 Km)
Cab
0 / Km
Rate
0 %
Surge Factor
Total
0
config.cac.toml
        
          
[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
        
      
Feature Packed
One Stop Solution for all your configuration needs
Superposition comes as a complete package that helps multiple teams across disciplines (front-end/back-end/operational/data) within an organization manage their configurations with a single instance.

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...

Trusted by all development teams across
juspay_white_bgnamma_yatri_white_bg
for developers, by developers
... and more to come
main.rs
                
                  
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(())
}
                
              
Main.hs
                
                  
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 ()
                
              
main.go
                
                  
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))
}
                
              
Application.java
                
                  
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());
        }
    }
}
                
              
index.js
                
                  
import {CacReader} from "superposition/clients/js/index.js";
import config from "./config.json";

const Cac = new CacReader(config);
const resolvedConfig = Cac.evaluateConfig({"country": "india"});
                
              
index.js
                
                  
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);
                
              
main.py
                
                  
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()
                
              

Superposition