Principles for API design

I made this list recently after we had a few incidents in a short timespan. I realized all of them were caused by skipping a good practice that we already knew about, but forgot or decided to ignore. This serves as a list to reflect on if you're making the right decision on your API to ensure long term quality.

  1. API First: Our code is used often but modified rarely. Optimize for readable, intuitive, and consistent external APIs, even if it means a slightly more complex internal implementation. When possible, align with native APIs for a smoother learning curve and better discoverability.
  2. Prioritize Simplicity, Accommodate Complexity: APIs should make common tasks easy while still offering the flexibility to handle more complex use-cases. Cater to the 99% without ignoring the 1%; it's okay if advanced functionalities require a few extra steps.
  3. Single Source of Truth: Data should live in one place, and state should flow unidirectionally. Question if a new piece of state is independent or if it can be derived from an existing state. If it can be derived, it probably should be. Eliminate redundancy to prevent bugs and confusion.
  4. Avoid Magic: Features should be explicit and predictable. Avoid unexpected functionalities, code should not be mysterious. Components should do what you expect and nothing more. Prefer clear over clever.
  5. Plan for Deprecation: Build as if you'll eventually replace your own code. Make features opt-in so you can know who is using them and what could break if you remove them. Plan for a future transition by reducing risk areas and documenting complex code. Reduce API footprint where possible.
  6. Fail Early: The faster you fail the faster you detect issues. Use the compiler as your first line of defense. In development, errors should be loud and clear so they're noticed immediately. In production, errors should log but avoid crashing if you can safely recover from it.
  7. Reusability & Composability: Design components to be reusable and extensible in different contexts. Larger components should follow a building blocks approach where smaller parts with single responsibilities are composed into one. Provide sensible customization points but avoid API bloating.
  8. Testing & Troubleshooting: Set the example for high quality testing. Prioritize critical paths and edge cases. Tests should be robust yet easy to understand, and runnable in isolation for quick validation. When unexpected behavior occurs, it should be easy to debug.
  9. Document for Everyone: Provide clear, comprehensive documentation with examples, edge cases, and tips. Good documentation acts as both a guide and a contract between the API and its users. The information should be useful to both new and seasoned developers.
  10. Community & Collaboration: Encourage team contributions and feedback to refine and strengthen your components. Take into account different points of view and expertise to ensure you're building something that works for everyone.

Subscribe to Gabriel Lanata

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
[email protected]
Subscribe