Live data from Hacker News

The Valley of Webhooks

weli.dev

41–50 of 108 posts

Re: The Valley of Webhooks

#41
I had this almost exact discussion today. Adyen (the payment provider) provides merchants with webhooks so they can update a local modal of payment and payment modification data (checkout).

But there is no way (for a merchant) to get the latest 'true' state as held by Adyen. So you better hope your data is exactly in sync with the notifications you got from the webhook (which it never exactly is, because there are so so many points of failures, and unlike what this author says, the docs aren't thát well presented to hold the same model as the PSP does. It is often close enough though, but you are constantly gardening your implementation, because the model also changes on their end with little information in the changelogs).

The "latest state" data exists though! If you open the customer portal it is presented to you without problem.

Re: The Valley of Webhooks

#42

Dude is not wrong ... but good luck convincing the Internet to switch to a sane system, when everyone already thinks web hooks are a "solved problem".

I can't imagine any reasonable engineer thinking webhooks are a solved problem. Imagine how much time and effort those provider must spent to offer high quality webhooks, to then still get customers complaining about missing packets and such. Webhooks are an operational nightmare.

Re: The Valley of Webhooks

#43
With the proposed solution every consumer will have a persistent connection to the server irrespective of the frequency of events. This setup seems inefficient unless you have a very high volume of events coming in. Many CDN networks have a limit on how long a connection you can open. And data providers will not prefer serving persistent requests.

Problems listed are signatures, dedup, buffering, bootstrap, cron. Everything other than signatures and bootstrap, can be solved by having a counter in every webhook payload. It will increment each time. When you receive a webhook and the counter does not match, the consumer can fetch the missing data from the events API.

I agree with the author that providers simply saying "at least once delivery" is insufficient. they should have solutions that does not require an architecture diagram.

Bootstrap is better served with a bulk events API so you don't make one call per request. It can have an after/cursor pagination. Solutions that work for our internal Kafka might not be suited to work across services, over the internet.

Re: The Valley of Webhooks

#44
This article resonates with similar struggles I've had at multiple companies. Its content is valuable. I wish the writing and the article itself had less of a slop odor.

That aside, what I don't understand (especially having worked on the side of the webhook sender, which is itself really tricky to get correct/performant/cheap) is why more companies which broadcast webhooks don't, say, provide direct access to Kafka topics, S3 buckets with ordered data objects landing, SQS queues, or any of the alternatives to those things.

"But it's irresponsible to expose an internal-use-only datastore directly to clients" goes one objection. But plenty of log-store systems have the notion of sharing a subpart of the log with a less-than-trusted external peer, so while exposing Kafka directly might be asking for the same kind of trouble as exposing your customer's SQL database for authenticated connection over the open internet (e.g. "we said you could issue reads, not that you could open/close TCP connections a million times a second! You just took out our message broker!"), exposing, say, an S3 bucket or Kinesis stream is much less risky because those systems have put some thought towards semi-trusted sharing.

"But everyone is used to getting HTTP webhooks and doesn't have the expertise to connect to something else"--that'd be true if, say, reading from a websocket or Postgres NOTIFY stream or Kafka topic or S3-change-notification stream were advanced techniques, but libraries around those things are so good nowadays that even the most web-tech-only low-skill developer can probably integrate with them with minimal hassle. Maybe it's just that a lot of shops literally only know how to run their code in a webserver, and have never deployed any other kind of application service/cronjob/queue worker? That seems unlikely to me, but I might be surprised.

"If we do something weird our competition will beat us on ease-of-use" goes another objection. But is it that hard given the libraries available? And can't you hedge back on the ease-of-use sell with "our data is fresher and more provably ordered and correct"?

I'm glad that SCROLL exists as a possible solution here. I'm just puzzled why more people haven't been using existing technologies to achieve this property.

Do most webhook senders literally not have a log store? Are they just firing webhooks in the middle of business event handlers and giving up synchronously if they can't be delievered?

Because if that's not the case (and I don't think it's the case), then it seems like the SCROLL API is ... basically just the Kafka consumer API. Or Kinesis. Or SQS. And so on.

Re: The Valley of Webhooks

#45

This article resonates with similar struggles I've had at multiple companies. Its content is valuable. I wish the writing and the article itself had less of a slop odor. That aside, what I don't understand (especially having worked on the side of the webhook sender , which is itself really tricky to get correct/performant/cheap) is why more companies which broadcast webhooks don't, say, provide direct access to Kafka…

We (Svix, webhooks infra) actually help our customers directly write to Kafka topics, S3 buckets, SQS, etc. and have for a few years now. There are definitely people that adopt that, but receivers as well prefer the simplicity of webhooks.

Re: The Valley of Webhooks

#46
post #32

This is a nice writeup of the problems in using Webhooks for State Synchronization. I also noticed that the proposed solution is a pseudo IETF-style draft protocol called SCROLL... that happens to be remarkably similar to an actual IETF draft I am bringing to IETF 127 this November called "Braid-HTTP Subscriptions." Both drafts request a subscription with a GET plus a header: Scroll Request: GET /scroll/feed/customer…

There’s also the Linked Data Event Streams (LDES) standard, which is a way of hosting a log as a set of linked http documents, fetched via polling and link navigation. Is there really anything more needed than a webhook for the notification and an LDES for the log?

https://semiceu.github.io/LinkedDataEventStreams/releases/1....

Re: The Valley of Webhooks

#47
post #3

The end here reminds me of "The Log: Real-time data's unifying abstraction" [0], which has unfortunately had a bit of link-rot since 2013. One complication in this approach involves access-windows: What if my system is only supposed to be seeing stuff that happened during two separate weeks in the year, because those are the spans when it was subscribed or authorized? So the data-host would need to maintain a concept…

That requirement seems ... uncommon. How many systems/industries have a frequent notion of transient/sliced views of history for their customers?

If that is a real requirement, it seems like it'd be easier to meet by giving customers a realtime-stream/log API whose history starts when they were most recently granted access, and providing them older historical events via a separate API of the classic "ask for a report and we'll get back to you within a day or two with an S3 presigned URL" variety, then synthesizing that huge historical report in batch code that's aware of the subtleties of the customer's visibility windows.

Re: The Valley of Webhooks

#48
You don't really need a new protocol. If you trust your consumers, you can just give them a paginated "/events" endpoint and have them poll that. The delay will be variable, but tunable, based on the required timeliness. If you want more prompt responses you do long-polling or a websocket.

The key, and only thing that matters, is that the cursor rides in your database, and is therefore transactionally consistent with the event. That's the whole magic trick.

We've done event streams like this at the bank I work at for years.

Re: The Valley of Webhooks

#49

I wonder if this is a CS problem somebody solved in 1954. Does somebody have the link to that paper? (I'm not serious about 1954 in particular, I am about hoping somebody here knows the CS literature better than me)

The old timey systems modeled this problem using accounting 101.

When things change, you don’t immediately update the balance. Instead it is written to a transaction journal aka a log. The thing is this log is the source of truth. State or the balance is derived from the log.

You don’t send a continuous stream of logs. Instead it is batched and sent asynchronously. It is also applied asynchronously. It also records if the batch was successful or not.

If you have multiple systems sending their logs to a central server. No problem. The central server orders them all before applying the batches.

Every so often. The books are “closed”. Meaning the central server won’t accept any more journal entries for things that happened older than X dates.

Re: The Valley of Webhooks

#50
Seems like we are trying to solve 2 problems at the same time with SCROLL:

* Database sync of log events. * "Real" time updates.

Webhooks can already mostly handle the "real-time" event portion. Of course there are problems. as the article expounds on, but a lot of those won't magically get solved with other solutions either. Distributed real-time communication is hard. Webhooks are good enough for this purpose.

For the database of log events, personally I'd rather just have a SQLite DB I can yank whenever. Don't give me CSV or JSON or whatever I have to parse and manage, just give me a SQLite DB ready to go. I'd love you for it. I'll just take a whole fresh copy with everything thanks. Maybe you limit it to to the last X events, say 90 days or 365 days or whatever, depending on sizing of events, but just send it all every time I fetch and I'm happy enough. If I need to generate a delta to keep some other DB in sync, well that's my problem. Just give every row a stable identifier.

Post reply on HN