Stop Polling and Consider Using REST Hooks

Web APIs have been around for a long time now. While that means there’s a lot of great tools from a lot of amazing developers, it also means that, as a community, the API space has held on to some practices for a long time — some would argue too long in many cases.

One such holdover, according to some developers, is the concept of polling. While polling itself is not a bad thing — after all, it’s a simple implementation of an endpoint call — many argue the effects of constant polling require a solution, and an immediate one at that.

Enter REST Hooks. Today, we’re going to take a look at the concept and application of REST Hooks, and exactly why some argue for their necessity. We’ll discuss some objections to the idea of polling, and the responses from their supporters.

What is the Polling Madness?

Polling Madness was a concept championed by API provider Zapier in 2013. Essentially, it simply states that the pattern of having a client routinely call an endpoint for new data, called “polling”, is wasteful. Constant polling of an endpoint is wasteful in terms of resources committed to the action from the developer, in terms of the traffic seen by the vendors, and in terms of actual result to effort. It’s estimated that 98.5% of polls are wasted.

While there are some objections to throwing out polling in it’s entirety, it’s got some merit to it, especially in the modern day of lean, efficient processing.

Polling is the same as the refresh button. It’s not a viable solution.

Part of why polling has stuck around for so long is because it is ubiquitous – until recently, there were very few effective ways to limit the negatives of polling, and because everyone was doing it, it was a very hard proposition to get other developers to move away. At best, you’d get a new solution that was a distant third option, and at worst, you’d get a powerful but ignored product.

The problem is that polling is essentially just hitting a refresh button – and, just as if the user was hitting the refresh button themselves, depending on a “refresh button” for vital functionality and data updates is unacceptable. Developers often turn to webhooks, but they can be difficult to set up.

The Solution

REST Hooks have been conceptualized by Zapier

The proposed solution described at resthooks.org is actually quite simple – POST a subscription /api/hooks that collates hooks at a target URL, which then pings the resource requester when a change is noted. It’s a subtle change, but it moves resources from constant rechecking in active fashion to passively waiting for updates.

According to Adam Duvander, subscription webhooks equate to a better user experience:

“Webhooks, particularly subscription webhooks like RESTHooks, are a rare triple win. They benefit everybody. The developer doesn’t have to poll 50+ times to get a single result. The provider’s server gets a breather. And the end user, often forgotten in these discussions, still ends up with near-instant results.”

Counter Arguments

One of the chief arguments against REST Hooks is that it flies in the face of REST itself. REST is specifically supposed to be session-free, and so the idea of creating a constantly polling, static URL on a session-less system seems counterintuitive.

Further issues are raised with the idea that there’s no current solution which does what REST Hooks is intending on doing. Some would argue that this, too, is false – TCP/IP websockets should be capable of doing what is being asked of the REST Hook.

The issue really, then, is one of effectiveness. Yes, it is true that REST is session-less in most implementations, but that does not mean that one can’t benefit from the positive attributes of session-ful communication while maintaining the overall benefits of REST. So too is the argument for TCP/IP somewhat flawed – yes, TCP/IP websockets can somewhat do what is being asked, but there are issues (loss of control for the user, less customizability, etc.) in those approaches.

So REST Hooks should be seen for what it is – one of many viable solutions, unique in its application, that can be used to solve a complex, consistent issue in a new, unique way.

Implementing REST Hooks

Conceptually, implementing REST Hooks is rather simple, though it does come with specific concepts that must be adhered to to technically consider it a REST Hook. REST Hooks are essentially URLs which collate changes that would usually be polled, providing a URL that can be actively monitored.

Create a Subscription

In order to escape the issues of polling a webhook, the webhook itself needs to be tied to a subscriber URL. This can be done with a simple POST element:

POST  \
    -H Authenticated: authenticationSolution \
    -H Content-Type: application/json \
    -d ‘{"target_url": "https://hooks.zapier.com/hooktest",
        "Event": "user_created"}’

This chunk of code sets up the URL by which you can direct polling webhooks to the REST Hook. It uses the standard authentication/authorization solution you’ve already implemented. Zapier responds with three elements:

  • Authenticated User
  • target_url
  • event

All three of these items are stored in local persistent data, which can be called upon when accessing the REST Hook. Of note is that Zapier recommends a few status codes for certain behaviors. For successful subscriptions, a 201 code, signifying “Created”, should be returned. Likewise, when a non-unique subscription URL is set, a 409 code should be returned, signifying “Non-Unique”.

Sending Hooks

Now that the hook is setup, we need a way for the API to actually send the data. We can do this by implementing the following POST code:

POST https://hooks.zapier.com/testhook \
    -H Content-Type: application/json \
    -d 

Zapier notes that they typically expect an array of objects – if the API sends a single object only, it needs to be wrapped in the following element array:

[ {"element1": "Content1", "element2": "Content2"} ]

Unsubscribing and Setting Up a Global URL

Finally, a DELETE call is made to unsubscribe using the following code:

DELETE  \
    -H Authenticated: authenticationSolution \
    -H Content-Type: application/json \

In order to define a polling URL permanently, there is an option to set up a trigger. This trigger will allow a user to set up a permanent data point, rather than having to create a new one to poll the endpoint. The polling URL alleviates this issue, creating a permanent location to draw information and data from.

Watch Audrey Neveu weigh in on the end of Polling & creating data streaming APIs:

Alternatives

WebSockets are bi-directional, so basically they tell both the client and the data to send that data to each other. Server-Sent Events is unidirectional – its an open channel where data can be streamed from the server to the client.

There are some alternatives to the REST Hooks approach, of course. WebSockets can provide a constant back and forth connection, negating polling in a way by moving the relationship from single-directional “pull” to “push”. This is questioned by some, though, as being essentially “polling 2.0”, in which the polling is from two sources rather than one.

Server-Sent is yet another solution. In this approach, the server does not respond to a poll request, but instead constantly “pulses” changes to the client itself. The problem here is that, while it removes the polling technically, it also removes much of the control from the user, and forces them into a passive state.

Because of this, many feel that both solutions are essentially inverse versions of polling, and are thus not acceptable solutions. Given the use case, they might be appropriate, and in others, they could be opposite of what is needed.

Conclusion

Implementing REST Hooks can solve a huge problem, but it rests on the developer to figure out how much an issue it truly is – on the one hand, polling is a consistent resource dedication that can result in slower response times when multiplied over many hundreds of connections.

On the other hand, there are many solutions that already exist, though they each have strengths and weaknesses opposite that of the Zapier REST Hook solution. If a developer does not have a polling solution, this is a fine one indeed – if, that is, the developer believes they have a problem to begin with.