Split offers a unified feature flagging and experimentation platform. When customers connect to Split and use it, they need to install what are called SDKs.
These SDKs are libraries which each customer puts into their applications. In order to start using a SDK for feature flagging and experimentation, the SDK needs to be instantiated with some fields such as APIKey. SDKs enable the communication between Split servers and client applications. The SDKs are open source. One of the advantages of the SDKs being open source is that they’re publicly available, welcoming other developers to contribute with bug fixes and suggestions (you can take a look at our php contributors guide).
Adding features and working as a developer for SDKs is not necessarily an easy task: There are several aspects that you need to worry about when you add code, release a new feature, iterate changes, or triage bugs.
Here’s what I’ve learned from experience:
Consistency and Parity Is Crucial
If you have SDKs for several languages, you need to be consistent across all of them. Split considers parity in the sense that we try hard to replicate every feature on all SDKs. The language and the application ecosystem (i.e., web server) sometimes have constraints that prevent us from having 100% parity across all languages. But, the coverage is still high enough for our users to feel comfortable when working on applications that spawn across more than one language. You need to plan ahead how much time adding new features across all the SDKs will take and try not to delay it.
Along with feature coverage, you should be consistent regarding the configs of the SDKs. The SDKs need to have the same sort of configurations between them in order to make it easier for customers to instantiate more SDKs for other languages. If SDKs are similar and consistent, the next configuration will be quicker. Consider this: Lack of parity and consistency can create confusion and unexpected behavior between the SDKs.
Always Stay Up-to-Date
Split started several years ago. Since the first version of SDKs , several features and improvements have been made. It’s good practice for customer apps to always keep libraries up to date. However, sometimes it’s not possible to update a version of a library immediately. If you use a library, you will probably need to work on it during the next deployment cycle of your app. This might not happen right away. It could take a few weeks or even months to catch up. Plus, you’ ll need to check if updates are still compatible with your app, ensuring nothing breaks. As you can see, there’s much to consider when making sure your clients are using the latest SDK version.
Make Proactive Improvements, Eliminate Tech Debt
There are always new ideas and improvements that can be executed to improve SDK performance as well as add cleaner logic. SDKs use libraries that sometimes incur vulnerability fixes. You need to set scans periodically to SDK repos in order to double check if libraries need updating. Depending on the severity of the vulnerability, expect deadlines for repair.
Test, Test, Test Again
You need to detect issues before going to production. Moreover, you need to make sure that every SDK returns the same outputs for the inputs provided. Every SDK has their own CI/CD pipeline, their own battery of unit and integration tests. In addition, there is a stage environment which simulates customer applications running tests for all the APIs that the SDK offers.
The Easier the SDK Is to Understand, the Better
You’ve got enough to worry about as it is, especially when considering the complexity of the public APIs and configurations you add. That’s why SDKs need to be easy to understand and easy to use. You want to build something that can be configured, installed, and used in minutes. Then, by reading the official documentation, you can offer more configs for running the SDKs with different recipes and different types of storage.
As previously mentioned, the SDK code is bundled in customer applications. If an error occurs inside the SDK, you must try not to break the client app. To minimize the possibility of crashes propagating from the SDK to the client application, all of our public methods (except the factory construction) swallow exceptions. Low-level system errors, such as an out-of-memory error, are excluded. By returning a special treatment control, the SDK indicates to the user that the evaluation could not be performed. Remember to document the cause of failure in the SDK log.
Give Yourself Time for Support Tickets
You are a human being, and you can potentially make mistakes. Don’t stress it. Support tickets will arrive, and you will need to try to replicate the issue in order to fix it. Customers will use the SDK in a wide variety of scenarios, each with their own singularities and inherent complexity. Whenever an issue is reported, you need to do your best to try and reproduce such scenarios as faithfully as possible (and provide a workaround if you can). Here at Split, we use Agile methodology for developing processes. You need to give yourself space in case something problematic arises. Allow yourself plenty of room to release new features and dedicate time to customer support tickets.
Backward Compatibility Is Your Best Friend
Backward compatibility between versions is a major ally when it comes to maximizing adoption. The lack of breaking changes in the API and functionality-related contracts implies that it’s safe for a customer to upgrade to the next version. They don’t need to update the code, or, even worse, be subject to a change in any specific functionality not reflected in a contract (for example a change in a default value). At Split, the SDK team makes an enormous effort to avoid breaking changes until the burden is way too heavy to maintain. An example of this is Python2, which was supported by our SDK way longer than its EOL date.
Developing SDKs can be challenging because they require some foresight and planning. At Split, we believe that the success of building and providing a library for customers depends on many factors including ease of use, reliability, failure proofing, and speed to repair.