Handling multiple identifiers at the Client

If you happen to be working with Split only on the server-side, you may not be aware of situation where the SDK needs multiple keys. A server-side example:

var treatment = client.getTreatment('susan', 'feature_flag_name');

If Susan is the user you want to evaluate, you pass susan right in the getTreatment call. But on the client-side, getTreatment is different.

var treatment = client.getTreatment('feature_flag_name');

What happened here? The answer is that susan appeared in the SDK configuration.

var factory =  splitio({  
	core:  {  	
			authorizationKey:  'your_split_api_key',  
			key:  'susan'  // unique identifier for your user  
	}  
});

And this is well and good if the only user you need to evaluate for that screen or page is Susan.

When do you need multiple identifiers?

One common situation is to conveniently bridge two Split traffic types, for example user and anonymous. Split is generally used to treat these types of traffic differently, separate flags and experiments. If you’re prepared to evaluate both keys, you can smoothly feature flag all elements of your screen or page.

There are less common situations that are application-specific. If you have identifiers that can be combined with other identifiers, you may want to feature flag the combined identifier. In B2B applications, you might evaluate many partner or store identifiers to produce a single page.

If you think you have one of these situations, you have options.

Using the SDKs to Instantiate Multiple Clients

Split’s documentation has a little section devoted to this:

In Javascript, you can get a new client from the factory:

const anon_client = factory.client('susan_anon_id',  'anonymous');`

You don’t even need to specify traffic type (it would be used if you did a ‘track’ call). You can switch users with simply:

const anon_client = factory.client('susan_anon_id');

A more complete example of managing logged in and anonymous ids?

	function uuidv4() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
      });
    }

    const wallet = {
    	user_id: 'dmartin',
    	anonymous_id: uuidv4()
    }

	var factory = splitio({
	  core: {
	    authorizationKey: 'your_split_api_key',
	    key: 'placeholder'
	  }
	});

	const manager = factory.manager();
	manager.once(manager.Event.SDK_READY, function() {
		let splitViews = [
			manager.split('anonymous_split'),
			manager.split('user_split')
		];

		let anonSplits = [];
		let userSplits = [];
		for(const view of splitViews) {
			if(view.trafficType === 'anonymous') {
				anonSplits.push(view.name);
			} else if (view.trafficType === 'user') {
				userSplits.push(view.name);
			} else {
				// unexpected traffic type
			}
		}

		const anonClient = factory.client(wallet.anonymous_id);
		anonClient.on(anonClient.Event.SDK_READY, function() {
			for(const split of anonSplits) {
				console.log('anonymous = ' + split + ':' + anonClient.getTreatment(split));
			}			
		});

		const userClient = factory.client(wallet.user_id);
		userClient.on(userClient.Event.SDK_READY, function() {
			for(const split of userSplits) {
				console.log('user = ' + split + ':' + userClient.getTreatment(split));
			}			
		});	
	});

Note that I have called SDK_READY callback after switching keys. You need this to make sure the SDK has updated properly.

Are all SDKs the same?

No, they’re not.

Some SDKs, like Flutter, ask that you instantiate new SDK instances for each key. When you do this, be sure to use a unique Split API key for each instance; it’s important to how Split keeps track under-the-hood.

Check the SDK documentation linked above for your platform to get final word.

Do I have any other options?

You can choose to use the Evaluator, or you can do the feature flag evaluations on the server-side.

Using the Evaluator involves replacing your SDK usage with HTTP transactions. You host the Evaluator locally, so it is likely to be high performance and secure, but a different network architecture from the SDK. The Evaluator is popular in situations where no SDK is available, but it is feature equivalent to the SDK, so you don’t miss out on any Split features by using it. Each Evaluator transaction can use an entirely different key.

Server-sider evaluation is a final option. If you want to evaluate not just two, but dozens and dozens of different keys, the computing pattern is well served by server-side SDK. As shown at the beginning of the article, a server-side evaluation can take a different key each time. By building a small service or proxy around your multiple evaluations, the client can call the server for the expected results. The convenience of this approach is a function of development practices and network architecture (if calls between the client and server are fast, this tends to be more attractive).

Final Thoughts

If you need to handle many keys on the client-side, you have a variety of options available. Keeping it on the client is usually the best approach, but if you have special needs to handle many keys at once, you might want to go with a hybrid approach – SDK and Evaluator – or create proxy services on the server-side to handle the high volume.

In my own experience, you can manage about a half dozen or so SDK instances. If you are on a platform where the SDK lets you swap keys, you can reach around a hundred or more keys (sometimes with warnings).

When you need that many keys or more, I go with a “hybrid” SDK + Evaluator approach. The SDK keeps a streaming connection open for updates on any changes to the flags. Then I evaluate all keys against the a Split Evaluator instance. With this approach, I can do more than five hundred keys, maybe even a thousand without too much delay. This can be compelling when the display is live updating in response to the flag evaluations.

This is an art and not a science, so consult your Split expert with questions!

DBM
david.martin@split.io