I'm a developer at Braintree. The challenge with maintaining backwards compatibility on the server side is handling the wide variety of possible inputs into the system. It's hard to write tests that account for all of them.
I've seen a couple of cases where backwards compatibility can be broken in unexpected ways. For one application that we built at Braintree, we had a client that was sending us an application/x-www-form-urlencoded POST body without the Content-Type request header. We upgraded the version of Rails that this app was using, and it broke that integration because Rails made a change where it wouldn't parse the POST body without the Content-Type header. Unfortunately, we didn't have any test cases in our test suite that made POSTs without a Content-Type. We were able to identify the issue and resolve it quickly, but it was a surprising bug. With client libraries, we can test every version against the upgraded app and know that all clients will continue to work.
Are there interesting request profiling techniques that can be executed on production traffic to analyze requests? I think the challenging part of backwards compatibility is making sure unintentional use cases, that were never intended to be supported, continue to work.
Thanks for responding! And I'll update my response to the backwards compatibility to say that I see the value in having a closed set of clients that you need to test for backwards compatibility.
That said, these are some of the things that I've done to help with backwards compatibility through only the serverside API:
* Track production requests and use them as test cases
* Build a large suite of test cases against the API
* Build the API in a statically typed language (yeah, I know, contentious, I love Rails but there's something about an externally facing API that makes me want to use a statically typed language).
* And then the ultimate -- build the API as an app that talks back to the business logic... essentially, it's your 'client library' but deployed on the server between the actual code and the client. Then, never change the part of it that faces the client, only the mappings on the the real business logic.
If you are going to make the decision and commitment to supply client SDKs instead of a RESTful API why choose to implement the back-end as a http service? It is now hidden entirely by abstraction from clients and there are lots of efficiencies to be gained by using a custom protocol.
Did you evaluate whether a RPC pipe or distributed filesystem was a better fit?
I've seen a couple of cases where backwards compatibility can be broken in unexpected ways. For one application that we built at Braintree, we had a client that was sending us an application/x-www-form-urlencoded POST body without the Content-Type request header. We upgraded the version of Rails that this app was using, and it broke that integration because Rails made a change where it wouldn't parse the POST body without the Content-Type header. Unfortunately, we didn't have any test cases in our test suite that made POSTs without a Content-Type. We were able to identify the issue and resolve it quickly, but it was a surprising bug. With client libraries, we can test every version against the upgraded app and know that all clients will continue to work.
Are there interesting request profiling techniques that can be executed on production traffic to analyze requests? I think the challenging part of backwards compatibility is making sure unintentional use cases, that were never intended to be supported, continue to work.