Live data from Hacker News

APIs, robustness, and idempotency

stripe.com

41–50 of 52 posts

Re: APIs, robustness, and idempotency

#41
The trick with idempotency keys in practice is figuring out a good stable way to record and query them.

So you want your endpoint to only do something once. Fine, does that mean I need a table in the DB with every key I've ever seen?

The most pleasant way I've solved this has been to think of this as rate limits where the limit is once per forever. After that they fit nicely in a token bucket and rate limit caching solution. This is one of the most useful thing that I think https://www.ratelim.it/documentation/once_and_only_once does. (I built RateLim.it)

Re: APIs, robustness, and idempotency

#42
post #9

I authored this article and just wanted to leave a quick note on here that I'm more than happy to answer any questions, or debate/discuss the finer points of HTTP and API semantics ;) An ex-colleague pointed out to me on Twitter today that there are other APIs out there that have developed a concept similar to Stripe's `Idempotency-Key` header, the "client tokens" used in EC2's API for example [1]. To my knowledge th…

In principle, what you've built is quite similar to a cryptographic nonce [1], usually used to prevent replay attacks against authentication services, etc.

We use similar tokens in our API for idempotency as well, though we called them nonces. Standardizing a bit on terminology and how to implement them properly would be really helpful.

[1] https://en.m.wikipedia.org/wiki/Cryptographic_nonce

Re: APIs, robustness, and idempotency

#43
post #9

I authored this article and just wanted to leave a quick note on here that I'm more than happy to answer any questions, or debate/discuss the finer points of HTTP and API semantics ;) An ex-colleague pointed out to me on Twitter today that there are other APIs out there that have developed a concept similar to Stripe's `Idempotency-Key` header, the "client tokens" used in EC2's API for example [1]. To my knowledge th…

My team and I would love a blog post from you guys about the architecture of your idempotency tokens!

Our implementation is probably less sophisticated than you're thinking, but thanks! I'll pitch the idea to the team. To put it very simply, it's a middleware that stores a known response by an idempotency key's value and does a lookup on it on subsequent requests.

Re: APIs, robustness, and idempotency

#44
To me the most interesting thing that came out of this article was exponential backoff-retry. I've always used e (natural log) as the base for my exponential backoff, and never used jitter (all my apps are single clients that are just trying to hit the AWS API, and none run simultaneously and I don't own the other side of it).

By looking it up I learned the concept of jitter, which is how Ethernet works, and I think it's really cool.

Re: APIs, robustness, and idempotency

#45
post #9

I authored this article and just wanted to leave a quick note on here that I'm more than happy to answer any questions, or debate/discuss the finer points of HTTP and API semantics ;) An ex-colleague pointed out to me on Twitter today that there are other APIs out there that have developed a concept similar to Stripe's `Idempotency-Key` header, the "client tokens" used in EC2's API for example [1]. To my knowledge th…

In principle, what you've built is quite similar to a cryptographic nonce [1], usually used to prevent replay attacks against authentication services, etc. We use similar tokens in our API for idempotency as well, though we called them nonces. Standardizing a bit on terminology and how to implement them properly would be really helpful. [1] https://en.m.wikipedia.org/wiki/Cryptographic_nonce

There are similarities, but given that people are pretty use to the word "nonce" being limited in use to crytography, I'm not sure that we could say definitively that re-using it here would be less confusing overall.

From a more practical sense, the naming is most likely to stay unchanged just because a lot of people are used to already.

Re: APIs, robustness, and idempotency

#46
post #45

Earlier quoted context omitted.

In principle, what you've built is quite similar to a cryptographic nonce [1], usually used to prevent replay attacks against authentication services, etc. We use similar tokens in our API for idempotency as well, though we called them nonces. Standardizing a bit on terminology and how to implement them properly would be really helpful. [1] https://en.m.wikipedia.org/wiki/Cryptographic_nonce

There are similarities, but given that people are pretty use to the word "nonce" being limited in use to crytography, I'm not sure that we could say definitively that re-using it here would be less confusing overall. From a more practical sense, the naming is most likely to stay unchanged just because a lot of people are used to already.

Absolutely, I wasn't suggesting that you should change the naming. In fact I agree that nonce is likely not the best term for this.

But the concept as it applies to HTTP APIs is a great one that I think could have a broadly recognized implementation. Whether folks start adopting the "Idempotency-Key" header or some other approach, having awareness and maybe even a standard could be great.

Re: APIs, robustness, and idempotency

#47
post #45

Earlier quoted context omitted.

There are similarities, but given that people are pretty use to the word "nonce" being limited in use to crytography, I'm not sure that we could say definitively that re-using it here would be less confusing overall. From a more practical sense, the naming is most likely to stay unchanged just because a lot of people are used to already.

Absolutely, I wasn't suggesting that you should change the naming. In fact I agree that nonce is likely not the best term for this. But the concept as it applies to HTTP APIs is a great one that I think could have a broadly recognized implementation. Whether folks start adopting the "Idempotency-Key" header or some other approach, having awareness and maybe even a standard could be great.

> Whether folks start adopting the "Idempotency-Key" header or some other approach, having awareness and maybe even a standard could be great.

Oh yes, hugely agree there! Part of the reason that I wrote this is that I couldn't find much prior art around idempotency keys (there is some, but not much). I am at least partially hoping that people will remember this article (or that it'll show up in a Google search) as they're implementing their own similar concept, and re-use the naming.

Re: APIs, robustness, and idempotency

#48
post #43

Earlier quoted context omitted.

My team and I would love a blog post from you guys about the architecture of your idempotency tokens!

Our implementation is probably less sophisticated than you're thinking, but thanks! I'll pitch the idea to the team. To put it very simply, it's a middleware that stores a known response by an idempotency key's value and does a lookup on it on subsequent requests.

How would this handle a distributed system, where a request might be routed to a different backend server? Do you try to guarantee that a request is statefully resent to the same target each time? Do you force your idempotency keys to be stored in some kind of distributed database, like a redis cluster?

Re: APIs, robustness, and idempotency

#49
An "idempotency key" can also just be a resource URL. If you use an idempotent HTTP verb this works wonders and is also more RESTful:

PUT example.com/orders/abc123/charged

The first PUT starts charging. If the client disconnects and retries while the original charge process is already running on the server, the server can just await this already running process. And if the order is already charged, the server can just return the outcome of the charge.

As long as there is a unique URL for every state a resource such as an order can be in, you can uniquely identify every action on it on the server-side and re-attach to running processes.

Using unique URLs for each state is the main idea behind REST (REpresentational State Transfer). REST namely means just this: representing server states as resources (URLs).

Re: APIs, robustness, and idempotency

#50
post #30

Earlier quoted context omitted.

That list of questions is why I prefer retry and back-off to be separate from the internals of the http library. As a library user I need to work around the peculiarities of the particular service endpoints I'm integrating with. Backoff and retry aren't specific to the application/transport protocol through which a service is consumed. For example, (in the java world) the approach in libraries like hysterix, guava-re…

What do you recommend for JS?

Libraries that provide similar abstractions in js do exist (https://github.com/tim-kos/node-retry and https://github.com/MathieuTurcotte/node-backoff), but I'm not qualified to recommend anything.

Most of the colleagues I've had have rolled their own one off solutions when needed.

Post reply on HN