Many developers have contemplated developing a software development kit (SDK) at some point in their careers. There’s something about writing code for code that we developers find fascinating. In modern programming, there’s almost no code written that’s independent of shared, reusable code produced by a third party. It’s this collective knowledge and experience that enables us to create incredibly powerful and useful software with just a laptop.
At Instabug, we don’t treat SDK as an afterthought; our products are a collection of code libraries, orchestrated together, to create a robust framework that extends the usability and value of Bug Reporting, Crash Reporting, and App Performance Monitoring.
Over the years, our SDK matured and proved its mettle, and so did we. For that to happen, we had to overcome a steep learning curve that peaks in uncharted territory. And now we’re sharing what we’ve learned throughout this process.
Let’s jump in.
1. Think for scale
Eric Schmidt, former CEO of Google, once noted, “Every problem that we have is a problem at scale.”
Scalability is a challenge nearly every organization faces. But it’s not merely the number of clients that can be problematic; the issue is the need to handle each client’s user base flawlessly and provide an excellent experience for every end-user.
Every action that we perform has to be well-calculated and has to consider a potentially massive scale.
2. Avoid third-party code
The realm of mobile SDKs is tight. Therefore, we have to carve out only the most essential space. To keep ourselves accountable, we work with a simple rule: no third-party code. If we need something, we create it ourselves. And most of the time it turns out, “we didn’t need that lib anyway.”
Any library we use could potentially add hundreds of thousands of bytes and methods to the client’s app. But more importantly, we are third-party code. If we use third-party code, we introduce an added layer of complexity and increase the chances of something going wrong.
We learned that we have to invest the time, effort, and manpower to develop our own tailored solutions that tightly integrate with our products, avoiding abstraction-hell and convolution. At the same time, we have to be flexible to meet community expectations for tackling modern software problems.
3. Dedicate more time to testing
It’s not too much of a stretch to say that most developers deal with tests the same way they deal with chores; we can be lackadaisical and quite creative in finding excuses not to write tests. But in software-library land, there’s no actual guarantee of correct functionality or predictable behavior other than testing. Our system is mostly code, and code can’t be properly validated with mere observation and good measures. It has to be proven correct.
Think of it this way: we can run tests for UI apps that validate entire use cases automatically. Moreover, there are a plethora of sufficiently mature tools that already exist for UI automation and overall app instrumentation. But when it comes to testing beyond UI, it’s quite complicated. That’s because our core functionality is not user-facing UI, and automating tests for this functionality is more art than science.
This means that we have to devote a lot more time and effort to testing the SDK than app developers normally would.
4. Be a sensitive guest
We learned to continuously monitor our impact on our users’ apps; from size to performance and everything in between. The nature of our SDK is crucial to apps’ quality. But we understand that we’re a musician in a massive orchestra, all playing in harmony to produce the best experience possible. If we were to play to a different tempo, that harmony is gone.
Currently, the average app uses around 15 SDKs. That's why we’re exceedingly self-aware of our SDK size, resource consumption, and impact on overall app performance. We never tire of asking these questions when we’re working on a feature, fix, or refactor.
5. Prioritize main thread freedom
Regarding lessons learned from developing our SDK, Mohammed “Zak” Zakaria, our resident engineering manager and Android lead, immediately vocalized concurrency and parallelism. We take pains to ensure that our initialization or operational tasks do not burden the main thread.
Almost everything is loaded lazily, handed off to background workers, or runs on demand. I mean, our SDK helps you make sure that your UI is slick and animations are buttery smooth. We can’t help becoming hyper-aware of the importance of main thread freedom.
6. View all devices as equal
Zak also noted that because we try to support as many devices and OS versions as possible, we have to ensure our SDK works as expected on all supported devices.
The team brings up low-end devices in every discussion, often treating their performance as a benchmark for our SDK quality. We take huge pride in the effort exerted in supporting almost every device currently on the market and maintaining a strong/solid/baseline level of performance.
7. Guarantee security and privacy at every step
Instabug’s SDK runs on more than two billion devices of all types and in all regions of the world, within all sorts of apps. We have to take decisive measures to ensure client and end-user security privacy–as well as our own–given the gigantic amount of vital data and logs traversing the globe.
We encrypt every piece of data in transit and at rest. We uphold absolute transparency in the types of data we collect—and clients and users retain complete control over what data that is. And finally, you have to constantly test and audit your security and privacy policies and measures, strive to gain security and privacy certifications, and adhere to grand-scope privacy laws like the GDPR.
8. Blend in as much as you can
Our SDK offers several end-user touchpoints. In fact, our first product was the famous shake-to-report bug reporting solution for mobile apps, which quickly became the leading tool in the mobile bug reporting space. We understand the uniqueness of every app’s design language and theme.
This individuality is what defines and distinguishes apps while remaining part of a standard design that the user of this platform is familiar with. Our UI has to be 100% customizable to match every app’s look and feel, and we have to offer practical presets that allow for a quick setup.
9. Be part of the changing landscape
Maintaining compatibility is an ongoing effort. Technology evolves at a supersonic speed, and everyone is trying to catch the bullet train. But on a large enough scale, it always becomes a tradeoff to determine what we’ll adopt and what we’ll drop to offer the best overall experience for every single device, platform, and use case.
We embrace change, but we have to prioritize reliability and availability and wait for the right time to adopt some changes. I couldn’t believe how rigorous, and thoughtful the process of discussing a new change or adopting a new idea was when I first participated in one of these sessions. It is brilliant!
10. Simplify integration, setup, and customization
The now-legendary design of Google’s homepage has always fascinated and inspired me. It’s just a search bar. Simple, yet powerful. When developing an SDK, aim for this level of simplicity for integration and setup.
At Instabug, we take immense pride in the simplicity of integrating our SDK into your app. It’s one line of code. We also design our public APIs to adhere to Android SDK guidelines, design patterns, and paradigms to make it easy for our users to get the most out of our SDK with minimal effort.
Instabug is growing! Check out our open positions.
- SDK Development Stories: Interviews With Our Developers
- How We Migrated Our Front-End While Scaling at Instabug
- Why We Automated Our Front-End Testing at Instabug
- How We Migrated Our Massive Crashes Database
Instabug’s triple threat of APM, Crash Reporting, and Bug Reporting tools will empower you to optimize your app’s performance and deliver the high-quality experience your users expect and deserve.
Find out how you can optimize your app performance with Instabug