DEV Community

Ashwani Arya
Ashwani Arya

Posted on

Config Management

In a multi-tenant system—such as a SaaS platform or a chatbot used by multiple companies—it is extremely important to design a robust configuration system.

In this article, I am not covering which SaaS platform you should choose to load or manage feature flags. Instead, the focus is on designing a feature-flag system on the frontend.

This system is based on learnings from building a video-calling chatbot for websites, where it was critical to ensure that the frontend was highly configurable, so that each customer could have its own set of features and UI customizations.

Assumptions for this article

  1. The backend will provide tenant-specific configuration. Designing or implementing the backend is out of scope.

  2. Configuration values may be edited from multiple places. Handling conflicts and reconciliation requires a separate mechanism, which is also out of scope.

I kept the designing very simple. As simple things scales better.

We need a function that will be used in singleton pattern to provide config. When I say config think it is just a key and value pair.

High Level Overview:

Lets call whole system a Config Manager.

The basic operating model aka life Cycle is very simple.

The Config Manager has two phase.

  1. Bootstrap phase
    In this phase the final config will be created will be served to runtime phase using single pattern.

  2. Runtime phase
    In this phase the final sealed config will be used by other code branch.

This phase has two components:

1.ConfigReconciler: The reconciler takes the default configuration and the tenant-specific configuration, then uses a deep-merge strategy to produce the final configuration. It’s also important to avoid unnecessary deep nesting in the config structure.

2.ConfigSingleton: Once the final configuration is computed, it is stored in a singleton, so it can be safely served to any part of the app that depends on it.

Integrate the bootstrap phase at the application entry point—typically main.tsx in Vite. The goal is to reconcile configs once during startup and avoid rerunning the deep-merge logic on every render.

Once bootstrapped, any component can safely read configuration via getConfig():

const config = getConfig(); 

if(config.buttonEnabled){
   return <button>Click Here</button>
}
Enter fullscreen mode Exit fullscreen mode

Thanks for reading. Happy building.

You can connect me on Github

Top comments (0)