Hacker News new | comments | show | ask | jobs | submit login
Don't Build APIs (kindel.com)
117 points by atularora 1651 days ago | hide | past | web | 57 comments | favorite

OP here.

When I wrote this post, I didn't imagine so many people would react by saying, essentially

"Screw the customers. Just break 'em."

One of the reasons I have my panties in wad over this topic is the Web has made it far easier for people to create APIs that get used by others. Back in the olden-days you HAD to be Microsoft or similar to get the kind of traction a kid in his parent's basement can get with a little Python and a Heroku account.

But something else has changed along the way: Composability.

Yes, I worked on COM, OLE, ActiveX and all that crap. I was thinking deep thoughts about composable software back in the stone ages (and even then, it had all already been done by others smarter than I in the 70s & 80s).

But today it is REAL. The Web technology stack has actually, finally, enabled massive distributed systems composed of loosely coupled components from multiple independent parties! The dream of my computing youth has become reality!

These things are connected by APIs.

(Which, by the way are not just function calls. A API can be a REST end-point, a file format, or a database schema, amongst other things).

Yes, you as an API provider can choose to deprecate your API anytime you want. Use kill-dates, warnmessages, etc... You can even create new, independent & parallel versions. It will help.

But you will find that someone else has built something that uses your API, that exposes its OWN API and now there's a 3rd party indirectly dependent on you. Be prepared for it.

APIs are actually easy to build. That is the problem. The solution is to realize that statement is actually false.

Two ideas on your post regarding potential technical resolutions.

First, in a web environment, one is probably logging all API calls and their effects on the server side. With Windows, you couldn't do that as your users were hitting local code rather than an MS server. This makes deprecation of older APIs much easier, in part because you can see which of your functions a particular API user is calling and in which order. Done right, these backend metrics will make it easy to identify the most popular use cases as well as functions that aren't used much.

Additionally, there was an interesting HN post from a few days back on self-describing APIs[1]. If this catches on, it will also make it easier to deprecate old APIs, especially if the OPTIONS request returns JSON. With a little bit of reflection up front, client code can then determine the most up to date way to achieve the effect they are trying to get with this API call. This may slow down client code (requiring one or more redirects up front) but won't crash it. Apple's support of Rosetta for PPC shows that slow emulation is a good intermediate between outright breakage (a la Facebook) and infinite grandfathering (a la early MS).

[1] http://news.ycombinator.com/item?id=3841710

I agree the mentality of "just break 'em" is wrong. But it's not so black and white. What you described is the extreme end of the spectrum that Microsoft is on. Clearly this is a pathological case where you commit to support abuse of your API. The alternative in this case would have been to tell Adobe not to do that earlier on. I understand why Microsoft operates that way, and I do believe it's an admirable goal, but you don't have to paint yourself into this corner. There are alternatives that are more subtle than screwing the customer. This gray area is what the thesis of your article skips over.

It's still a great story though.

However, you also have to realize that the business effect on Microsoft if their API break is vastly different than the one on Twitter if their API breaks.

If Microsoft break their API's, then people might not upgrade their versions.

Will people stop using Twitter if they break their API's? Definitely not, so why should they bother if some third part have to pay to fix their code?

OP, I really don't want to be that guy, and I don't know why I'm being that guy tonight, but regarding your sentence, "I then spent hours pouring over..." - come on man, it's poring.

I don't mind you being that guy at all.

I consider myself to be an ok writer with a reasonable vocabulary.

I never knew it wasn't pouring.

Consider me educated. Thanks. :-)

poring and pouring have different definitions - so pouring is correct for liquid, and poring is correct for poring over.

This post is very accurate. I build APIs for a living (CUDA), and this lines up pretty well with my experience. Writing APIs is very tough, you will get a lot of things wrong, and the fixes available to you after you realize your mistake are all ugly at best.

One quick example:

In CUDA, you have to explicitly copy memory to and from the GPU. We have two basic kinds of memcpy functions--synchronous and asynchronous. Asynchronous requires some additional parameter validation because the GPU has to be able to DMA that particular piece of memory, etc. After we had been shipping this for a release or two, we noticed that our parameter checking for the asynchronous call was missing one very particular corner case and would silently fall back to synchronous copies instead of returning an error. We thought, okay, let's just fix that by returning an error because surely no one managed to hit this.

Absolute carnage. Tons of applications broke. This particular case was being used everywhere. It provided no benefit whatsoever in terms of speed; in fact, it was just a more verbose way to write a standard synchronous memcpy. People did it anyway because... they thought it must be faster because it had async in the name? I don't know.

In the end, we made the asynchronous functions silently fall back to synchronous memcpys in all cases when the stricter parameter validation failed.

Well, if it helps any, I've found the CUDA API to be somewhat lacking in features, but more or less robust, and pretty logical to deal with as a developer. Keep up the good work.

Thanks for your work on CUDA, it's really a great tool! My one hope is that Nvidia decides to make it a direct competitor to OpenCL by allowing it to target different platforms (though I recognize that it's not completely up to Nvidia and requires cooperation from others).

What would be the value in competing with OpenCL? CUDA and OpenCL ship pretty much an identical feature set with small changes in the API. The biggest difference is that OpenCL requires you to use buffers+offsets where CUDA allows "pointers" to GPU memory.

It's nice that Nvidia has CUDA so they can go ahead and expose functionality in new GPU's without having to (first) deal with OpenCL standardization. However, for the long term, it would be better if we'd stick to OpenCL so at least parts of source code can be shared between CPU's and GPU's of different vendors.

Competition is a good thing, and CUDA isn't a direct competitor to OpenCL because it only targets Nvidia's platform. OpenCL is obviously the longterm winner because nobody in their right mind would want to lock themselves into a single vendor. I'm saying that I would appreciate it for Nvidia to challenge that, which will drive both CUDA and OpenCL to become better.

Crazy, you work for Nvidia? I love using CUDA for VRAY rendering. It still lacks a ton of the material support but its getting there. From your development, how much more needs to be added to CUDA and Video Cards to get more accurate renderings with full support of materials? I know VRAY has figured out some amazing ways to get around this and support multisided material recently.

CUDA does not know anything about materials, it's only an API to run code on the GPU and transfer data back and forth from main memory to gpu memory. So it's all up to VRAY devs to implement material rendering with the tools they have available.

As far as I know, there will be no revolutionary changes in GPGPU programming in the immediate near future (apart from badass-er GPUs).

Someone should get query MYSQL server working on Cuda.

At some point, we need to kill the myth of backwards compatible. This has caused more problems than it fixes. Further, at this point in history, app updates are trivial and built into everything, so retaining backwards compatibility is not so much of a necessity.

When designing APIs, use versions and have a kill date in place. Even if you don't change the API, release the same one under a new version number. Kill access to the old version on the kill date. Keep N versions accessible at a time, to reduce the burden on app writers, but don't slack on the kill date. This will give you a timeline and procedure to avoid hacking in crazy backwards compatibility, and targets for total rewrites.

Yes, people will still complain. It's OK though if you provide a reasonable balance.

Myth? MS built a very successful business on it.

You know what happens when you get kill dates? One day all of a sudden half the web will stop working. There's a reason why people start back flipping to support out of date calls.

Customers don't care why your software just broke or whose fault it was, all they care about is it broke.

I'm actually quite fond of the way Microsoft historically bent over backwards for backward compatibility, but OTOH Facebook is also very successful and has a very successful ecosystem of third-party users of their APIs. Facebook is like the anti-Microsoft in that they randomly change and break their APIs at such an alarming rate that you have to wonder if they are intentionally fucking with you if you code against their APIs.

Obviously the needs for a web API and the needs for an API with a specific binary ABI on a local OS are quite different but I think for either environment, most API developers can comfortably fit somewhere between those two extremes where they don't continue to support inherently unsupported API usage, but they don't break something randomly every week.

Facebook making breaking changes does piss people off. It's interesting that it doesn't kill the apps. I can't remember any single change Facebook have made - possibly just because tere's so many - but I do remember when twitter made everyone switch to OAuth. People complained about that kill date.

I think developers tend to love backward-compatability while users hate it.

As a developer, it means we don't have to keep digging out the old projects and porting them to the new API.

As a user, it means we are left with systems that have many years of cruft and with features being held back from systems because they couldn't make it backward-compatabile.

I think most users are willing to pay any higher price that will result from developers being required to work harder to port their software.

Users love it when their software still works even after they've upgraded another bit of the overall system.

As a developer, I would rather have my code break than continue to use a terrible API.

How about fixing your application, because your terrible API were deprecated, for an application that is quite old, bit still in support ? (and of course for free, because client don't expect to pay for a compatibility fix).

If you have your kill-date iterate rapidly enough, and advertise it well enough, people who build products on your API will keep up, or the competitors will and take their business.

Heck, if you want to be really hand-holdy about it, have an warnmesage attribute in your returns that mentions various issues, and start throwing deprication warnings some $time before the kill date as a reminder.

And the number of bugs and security holes coming directly out of backwards compatibility in MS products was a very big issue for a very long time. Lately they have been doing much less in terms of backwards compatibility (e.g. run in "compatibility mode"), probably as and outgrowth of this.

Or customers will switch to a competitor's API that doesn't keep trashing their app with "improvements' that are not usable for that specific app.

But your proposal is interesting: if things are improving all the time, API-users need to be upgrading all the time and adapting to the new features anyway - so any incompatibility necessary for those features is no problem.

It depends on the phase of market (new, growth, mature, stagnating) for that specific API. At the moment, most web-APIs usages are "new".

I think sophacles is onto something here.

In my post I tried to make it clear that backwards compatibility is a challenge for successful APIs.

However, I guess if you don't want to make your APIs successful you can do all kinds of things that make them harder to use, like putting in draconian kill-dates, warnmessages, etc... Make sure your documentation is extra-long and wordy too while you're at it.

Because, sophacles, is right: if you don't have a successful API you don't have to worry about pissing customers off.

This is a false dilemma. Just because you set up some opposing conditions: backwards compatibility or unsuccessful api doesn't actually make it true. Just an assertion.

Having a reasonable end of life on support never hurt apple. There are lots of things that I can no longer run on the latest version of OSX. This happens every time the OS upgrades. Except of course they don't use versioned APIs, so it is much less planned for and not really as easy to deal with for devs.

I'm not saying make a shitty API, I'm saying, if you have the people who depend on your product know that changes happen, they can prepare for it. If you release a new version of the API every 6 months, and only support them for 18 months, you can make the api migrate slowly enough that it isn't a serious change for each version.

In native code: anything compiled to old APIs can link to old versions of your library, and just work the same way. In web apis: the world changes faster than the 18 month thing anyway, so whatever.

If people want to depend on your bugs, you told them not to, they can deal with the changes.

"There are lots of things that I can no longer run on the latest version of OSX. This happens every time the OS upgrades."

This is what i hate about osx - they freaking change the OS drastically, and my apps break. Sure, there might be a new version, but when i compare mac OSX to windows, windows kicks ass because you know what? i can _still_ run crap that i used to run in win95!

Having a reasonable end of life on support never hurt apple.

Just because the iPhone is doing great, doesn't mean businesses and other slow movers avoid Apple because of this. My point is, we don't know if this hurts Apple or not.

Yeah, Apple has no success whatsoever with their aggressive deprecation strategy :)

> Myth? MS built a very successful business on it.

It's also an unsustainable business. How long do you think MS will be able to maintain backward full compatibility? 100 years? 200 years?

> Customers don't care why your software just broke or whose fault it was, all they care about is it broke.

Customers aren't engineers; they don't know better. We do. In any, it's going to be cheaper to abandon the stubborn customers than it will be to maintain decades worth of backward compatibility, at some point.

100 years sounds reasonable. Old APIs simply get frozen and new ones take their place. Apps written to .NET, for example, aren't bound by compatibility concerns with the early win32 GDI implementations. Cocoa apps aren't impacted by Carbon's compatibility concerns.

What's the option? Throw whole platforms out and start over every 15 years? Does that scale? It has so far only because the industry has been growing (more smartphones than PCs, more PCs than workstations, more workstations than minicomputers, etc...). But it won't grow forever.

*myth of backwards compatible"

What is the "myth" of backward compatible?

I wholeheartedly agree with your second paragraph regarding versions and kill dates - but every API is different. In our case, when our API changes/versions/deprecates - WE are directly held responsible by customers of consumers of the API - since API consumers trumpet the fact that they have integrated with our API.

On the surface, versioning and kill dates are great end-all solutions, but the reality is API consumers have a ton of leverage when your API is successful at generating revenue for you. Especially when those consumers are sending lots of revenue your way from their own customers, which think you are the source.

The key problem here is that "backwards compatibility" means "backwards compatibility for people abusing the API in undocumented ways".

Don't do that. That way lays insanity. Be very, very clear up front that you will break backwards compatibility for those folks. Don't sweep it under the table, be very vocal about having done it. There will be short term pain as important customers (eg Adobe) learn the hard way that you really mean it. And long term relief as you don't have that legacy headache growing so quickly.

One estimate is that a 25% increase in requirements results in a 100% increase in software complexity. (See Facts and Fallacies of Software Engineering for a source.) That means that the complexity grows as the number of requirements cubed. Therefore the key to a good API is that it be short and simple. When you start to add implicit requirements on top of explicit ones, it quickly becomes long and complex, and the necessary software to support it and make future modifications becomes much worse.

This does not mean that designing APIs is not hard. But don't let your API become what is published and quirks that are not. Just don't.

Your API documentation (or specification if you have one) is not your specification. Your API implementation is your specification, especially if you are the only provider of the API. I realize how trite that sounds, but it's true. Defensive API design (make it REALLY HARD to have undocumented tricks that developers can use in productive ways) is dramatically harder than API design is in the first place, and I still guarantee you'll screw it up for any moderately expressive API.

It's not just an issue of parameter validation or well-defined calls; it's the interactions between calls where this is hard. It's issues of ordering, timing, when you can secretly skip synchronization because you know the API will synchronize just enough for you to get away without something more heavyweight, things like that. And then when you have paying customers? Yeah, you can't break their code, even if it's bad, because if you do you won't have customers for very long.

OP here.

I think this is very naive/utopian.

Yes, be super focused in your design.

Yes, only expose APIs you have clear use cases for.

Yes, keep the surface area as small as possible.

Yes, have very focused requirements.

Yes, document the hell out of things.

Yes, implement strong parameter validation and other things to try to reduce the chance people do bad things.

Do all these things and more (these are all part of what makes exposing APIs hard work, that many people don't do).

But do not, for one second, believe that someone still won't do it wrong or abuse your perfectly designed API eventually... especially if it is successful.

I agree with all of what you just said. But I think that the post is not a good demonstration of that.

Microsoft failed at keeping the surface area as small as possible. When their surface area expanded to a hack to deal with Adobe's hack of replacing code behind Microsoft's back, they went into very dangerous territory.

If an end-user upgrades their operating system, and Adobe WhateverIUse stops working, who do they blame?

They will blame both initially. Pissed off people are pissed off, and distribute blame randomly. That is the short term pain. However if it broke AND Microsoft stated up front that it really was Adobe's fault, Microsoft would have taken less of the blame. Not none, but less.

The flip side if Microsoft had bitten that painful bullet up front, then I believe that going forward companies like Adobe would have learned to not try to hack the system like they had. That would have given everyone, including Microsoft, a better reputation.

But of course Microsoft did not do that. And now Microsoft has such a history of nasty bugs that, even if Microsoft is in the right, nobody is going to believe it. (Which of course locks Microsoft into its current strategy of bending over backwards to accommodate everyone else's bugs, causing more bugs...)

It's not as simple as that. If it's just Adobe WhateverIUse that breaks, sure, people will blame Adobe. But if it's Adobe WhateverIUse that breaks AND WordPerfect WhateverSomeoneElseUses and maybe also Borland SomethingSomeoneElseYetAgain uses word will get around that the new operating system "breaks things" and people will stay away from it.

Even if noone will ever use all three of the broken apps.

In this sense, maintaining backwards compatibility is simply a matter of reputation management.

> If it's just Adobe WhateverIUse that breaks, sure, people will blame Adobe.

Not a chance. People will blame Microsoft, because WhateverIUse worked perfectly before. The only parameter which changed is that they updated the OS, therefore the OS is to blame.


That is a wish, not the truth. It is self-evident that if I upgrade my OS and an app stops working, it is the upgrade's fault. I'm sure there is a "law" of "whoever last changed something broke it."

So, it's the users fault then?

If they'd done that to the 6502 CPU and variants, every single non-trivial game or program would have broken.

Behind almost every successful API is a big ugly mess of backwards compatibility to keep customers happy.

Upvoted because I find it interesting, not because I agree with it.

FreshBooks has a very significant amount of their usage/profit from their API. These are just their endorsed/vetted add-ons, let alone all the ones out there in the wild: http://community.freshbooks.com/addons/?header_addons=1 and they clearly built an app AND an API.

The API for FreshBooks was a major portion of their (very successful) strategy, so I can't see why people can't do both, provided they do it intelligently.

This post addresses many of the issues we've dealt with at RadioReference.com. We version our primary APIs which has worked very well, but occasionally we have to abstract and write translations for backwards compatibility. We also need at times to deprecate versions and features.

But, this quote in the post is important: "When exposing APIs be absolutely certain the value you get from doing so is worth it."

In our case, our APIs are a significant revenue driver and are worth it. Don't let OP discourage you from exposing your platform's data via APIs. Instead, let this post warn you what to look out for when exposing APIs.

This boils down to a simple question:

Are most of your API users ahead of you, or behind you?

If you have an immature API with a smallish number of users, and you think that incompatible changes in the API will improve adoption with the vast bulk of your (not-yet-on-board) potential market, then go ahead, break the API.

If the only reason people use your API is because of its legacy -- if you think that by changing your API people will wake up from their inertial slumber and investiate your superior competitors, then don't break your API under any circumstances.

Obviously there are grey points in between, and a series of small breaking changes will be worse than occasional large breaking changes. But by and large, the success of your platform will depend on its utility, not legacy compatibility. This is why stripe and wepay will eventually conquer paypal, why python will continue to be a vibrant community, why java will eventually fade to cobol-like obscurity, and why Microsoft Windows is fundamentally doomed. It's hard to look backwards and forwards at the same time.

This reminds me of a Joel Spolsky post from years ago:


Essentially, Microsoft shoots itself in the foot by trying to stay extremely backwards compatible, even to the detriment of making their products better.

Public APIs are forever – you get one chance to get it right. Unless nobody's heard of your API and thus nobody uses it, in which case you're safe, but also screwed.

Build the best API you know how to build and ask questions later. If your business is doing well, then supporting your API forever is a high quality problem.

This is often good advice, but not in this case. Versioning your API is a trivial thing to do from the beginning and has massive consequences down the road. Some things are worth getting right in the beginning.

My biggest issue with web APIs is the speed at which they change means you often get a lack of maintenance of documentation. The speed of change compounds the effects, the discussions you find on the API usage only months old have lost relevance in non obvious ways.

Facebook and Paypal are or have been guilty of this in the past though Facebook is a lot better than it was.

The OP's enemy is not APIs, but rather proprietary software.

Open source APIs and libraries improve this situation to some degree.

At least you wouldn't be stuck debugging assembly code.

Netsuite has a different url for each new version of their API (and they keep the old one live as well).

This was great for me because my code never broke, which was important because It was running the back-end of an e-commerce site. It gave me more than enough time to upgrade when I wanted bug fixes/features.

Yes! This wasn't what the OP was referring to, though: he had shipping shrink wrap software with APIs in mind. But still, you're totally right and this occurred to me as I was reading the post, for Web APIs: keep versioning the URL for every shipped revision of your API. You'll have to document like crazy, of course. You can even detect stragglers on old versions and help them get on the new version.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact