Building Internal SDKs That Developers Want to Use

Lessons from building KlivvrStorageKit on creating internal SDKs with great developer experience — covering API design, documentation, migration support, and adoption strategies.

business6 min readBy Klivvr Engineering
Share:

Building an internal SDK is easy. Getting developers to actually use it is hard. Every engineering organization has stories of well-intentioned internal libraries that were technically sound but never adopted — because the API was confusing, the documentation was sparse, the migration path was unclear, or developers simply did not know the SDK existed.

KlivvrStorageKit started as a response to a concrete problem: multiple iOS apps at Klivvr were implementing their own storage patterns, each with different security characteristics and varying levels of correctness. The SDK consolidated these patterns into a shared library. But consolidation only works if teams adopt it. This article covers the strategies we used to drive adoption of KlivvrStorageKit and the developer experience principles that made it stick.

API Design for Adoption

The single most important factor in SDK adoption is the API. If the API is intuitive, developers adopt it naturally. If it requires reading a manual before writing the first line of code, adoption stalls.

KlivvrStorageKit's API follows three design principles. First, make the common case simple. Storing and retrieving data should require minimal code and zero configuration for the default case. The security level parameter is the only required decision beyond the key and value. Second, make the right thing easy and the wrong thing hard. Storing sensitive data in an insecure location requires explicitly opting out of security — the default path is the secure path. Third, use the language's type system to prevent errors at compile time rather than runtime. Generic methods ensure type safety, and enums constrain security levels to valid options.

These principles are not unique to KlivvrStorageKit. They apply to any internal SDK. The common pattern of failed SDKs is requiring too much upfront configuration, exposing implementation details in the public API, and relying on documentation rather than types to communicate constraints.

Progressive Disclosure

A good SDK works at multiple levels of sophistication. A developer who needs basic storage should not be confronted with migration pipelines and biometric access control on day one. But a developer building a complex feature should be able to access advanced capabilities without switching to a different library.

KlivvrStorageKit achieves this through progressive disclosure. The top-level API is the SecureStorage class with its store, retrieve, and delete methods. That covers 80% of use cases. For developers who need caching, the CachedStorage wrapper adds an in-memory layer without changing the underlying API. For biometric protection, the BiometricStorageManager adds authentication flows. For data migration, the MigrationPipeline provides versioned schema evolution.

Each layer builds on the previous one without requiring understanding of the layers below. A developer using CachedStorage does not need to know how the Keychain works. A developer using BiometricStorageManager does not need to understand cache eviction policies.

Documentation That Actually Gets Read

Internal SDK documentation fails when it tries to be comprehensive. A 50-page document that covers every method and edge case will not be read. Developers learn by example, not by reference.

KlivvrStorageKit's documentation follows a three-tier structure. The first tier is a quick-start guide — a single page that gets a developer from zero to working code in five minutes. It covers installation, basic store/retrieve operations, and the three security levels. Nothing else.

The second tier is a set of how-to guides organized by task: "How to add biometric protection," "How to migrate from UserDefaults," "How to handle offline sync." Each guide is self-contained and starts with a working code example.

The third tier is the API reference — auto-generated from source code comments and available for developers who need to look up specific parameter types or method signatures. This tier exists but is not the primary learning resource.

The key insight is that documentation should be organized by what the developer is trying to do, not by how the SDK is structured internally. Developers do not think in terms of classes and methods; they think in terms of problems to solve.

Migration Path

The biggest barrier to SDK adoption is migration cost. If teams have existing storage implementations that work, the cost of switching to a new SDK must be justified by clear benefits and a smooth migration path.

KlivvrStorageKit provides migration utilities that read data from common legacy storage patterns (raw UserDefaults, untyped Keychain wrappers, custom file storage) and move it into the SDK's managed storage. The migration runs automatically on the first app launch after the SDK is integrated, so users experience no disruption.

For teams with custom storage implementations, we provide a compatibility layer that wraps their existing storage behind the KlivvrStorageKit protocol. This allows teams to adopt the SDK incrementally — new code uses the SDK directly while existing code continues to work through the compatibility layer. Over time, the legacy storage is migrated piecewise rather than in a single risky migration.

Measuring Adoption

Adoption is not binary. It is a spectrum from "installed but not used" to "fully integrated and relied upon." Measuring adoption requires tracking not just which apps have the SDK as a dependency, but how deeply they use it.

We track three metrics. Coverage measures the percentage of storage operations that go through the SDK versus direct Keychain or UserDefaults access. This identifies apps that have partially adopted the SDK but still have legacy storage paths. Security compliance measures the percentage of sensitive data that is stored with appropriate security levels. This identifies apps that use the SDK but store tokens or credentials at the wrong security level. Migration completeness measures the percentage of legacy storage items that have been migrated to the SDK.

These metrics are collected through build-time analysis (scanning for direct Keychain or UserDefaults calls) and runtime telemetry (counting storage operations by backend). They are published to an internal dashboard that the platform team uses to prioritize migration support for teams that need help.

Ongoing Maintenance and Trust

SDK adoption is not a one-time event. It requires ongoing maintenance, responsiveness to feedback, and a track record of stability. If an SDK update breaks an app's build, the team will revert the update and lose trust in the SDK.

KlivvrStorageKit maintains trust through rigorous versioning (semantic versioning with no breaking changes in minor releases), comprehensive testing (unit tests, integration tests, and device tests on every CI build), and a dedicated Slack channel where teams can ask questions and report issues. Response time to reported issues averages under four hours. This responsiveness is as important as the technical quality of the SDK itself.

Conclusion

An internal SDK succeeds not because it is technically excellent but because it is easy to adopt, well-documented, and actively maintained. KlivvrStorageKit's adoption across Klivvr's iOS apps is the result of deliberate API design, progressive disclosure of complexity, task-oriented documentation, smooth migration paths, and ongoing investment in maintenance and support. The technical foundation matters — encryption, biometric protection, and migration pipelines are genuinely valuable capabilities — but without developer experience, those capabilities sit unused in a library that nobody integrates.

Related Articles

technical

iOS Keychain Services: A Comprehensive Guide

Master iOS Keychain Services with this comprehensive guide covering item classes, access control, sharing, migration, and common pitfalls in Swift.

8 min read