Keep Your API Surface Small
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.
If the API is the documented contract exposed by an application, the API Surface Area encompasses all observable behavior from the API and any integration points. That is, API Contract ⊂ API Surface
. One benefit to open-source is that you don't need to design the perfect API for your customers. That's because the effective surface of the API you exposing is much larger – customers are free to modify the code, dig deeper into the implementations, or something in between.
On the other hand, even with well-defined API contracts, open-source projects end up exposing the full monty. Even if you think you're just shipping a Docker image or Kubernetes Helm chart, the integration points increase exponentially. Interfaces like storage, networking, and service discovery alleviate this problem a bit. But every observable behavior by each of these interfaces eventually becomes a dependency by some customer.
Why? Well, as a rule.
All APIs are leaky.
Not only is an API contract never sufficient in documenting all possible behaviors, but even when all cases are considered (they never are), all APIs are leaky. The abstractions we create work, most of the time. However, there are always times when the underlying complexity leaks through, a particular implementation that can't quite be ignored.
After working in both worlds for some time (proprietary cloud provider APIs and open-source projects), I'd say that the trade-off is between customizability and maintainability. Regardless of the delivery model on-premise or SaaS, you want to keep your API as logically small as possible.
I use the modifier 'logically' because otherwise the statement clearly doesn't hold in the extremes – imagine a single API endpoint that handles all types of requests. Too general of a contract and you're not saying anything at all.
A benefit of SaaS is that you end up shipping a much smaller API surface. Smaller API surfaces mean that you can iterate much quicker and change implementation easily without breaking contracts. But not even SaaS is safe from leaky abstractions.
So keep your API surface small.