About

Introduction

Pushpin is a reverse proxy server that makes it easy to implement WebSocket, HTTP streaming, and HTTP long-polling services. The project is unique among realtime push solutions in that it is designed to address the needs of API creators. Pushpin is transparent to clients and integrates easily into an API stack.

Pushpin is written in Rust & C++. Its name means to “pin” connections open for “pushing”.

How it works

Overview

Pushpin is placed in the network path between the backend and any clients:

pushpin-abstract

Pushpin communicates with backend web applications using regular, short-lived HTTP requests. This allows backend applications to be written in any language and use any webserver. There are two main integration points:

  1. The backend must handle proxied requests. For HTTP, each incoming request is proxied to the backend. For WebSockets, the activity of each connection is translated into a series of HTTP requests1 sent to the backend. Pushpin’s behavior is determined by how the backend responds to these requests.

  2. The backend must tell Pushpin to push data. Regardless of how clients are connected, data may be pushed to them by making an HTTP POST request to Pushpin’s private control API (http://localhost:5561/publish/ by default). Pushpin will inject this data into any client connections as necessary.

To assist with integration, there are libraries for many backend languages and frameworks. Pushpin has no libraries on the client side because it is transparent to clients.

1: Pushpin can communicate WebSocket activity to the backend using either HTTP or WebSockets. Conversion to HTTP is generally recommended as it makes the backend easier to reason about. See Proxying.

Concepts

Architecture

Pushpin fits well into a variety of setups, due to acting as a proxy server and as a publish-subscribe broker.

Basic:

The most basic setup is to put Pushpin in front of a typical web service backend, where the backend publishes data directly to Pushpin. The web service itself might publish data in reaction to incoming requests, or there might be some kind of background process/job that publishes data.

arch-basic


With API management:

It’s possible to combine an API management system with Pushpin. Most API management systems work as proxy servers as well, which means all you need to do is chain the proxies together. Place Pushpin in the front, so that the API management system isn’t subjected to long-lived connections. Also, Pushpin can translate WebSocket protocol to HTTP, allowing the API management system to operate on the translated data.

arch-apimanagement


With message queue:

If you have a lot of data to push, you may want to introduce an intermediate message queue. This way, backend processes can publish data once to the message queue, and the queue can relay the data via an adapter to one or more Pushpin instances. Pushpin is able to forward subscription information to such adapters, so that messages can be sent only to the Pushpin instances that have subscribers for a given channel.

arch-tiered


Microservices:

In a microservice environment, Pushpin makes it easy to listen for instant updates from other microservices without the need for a centralized message broker. Each microservice gets its own Pushpin instance, and microservices communicate with each other via your organization’s own API contracts rather than a vendor-specific mechanism.

arch-microservice


As a large scale CDN:

Since Pushpin instances don’t talk to each other, and message delivery can be tiered, this means Pushpin instances can be geographically distributed to create a realtime push CDN. Clients can connect to the nearest regional edge server, and events can radiate out from a data source to the edges. This is essentially the goal of Fanout.

arch-cdn

Why Pushpin?

Pushpin is an ambitious project with two primary goals:

To really understand Pushpin, you need to think of it as more like a gateway than a message queue. Pushpin does not persist data and it is agnostic to your application’s data model. Your backend provides the mapping to whatever that data model is. Tools like Kafka and RabbitMQ are complementary.

Pushpin is also agnostic to your API definition. Clients don’t necessarily subscribe to “channels” or recieve “messages”. Clients make HTTP requests or send WebSocket frames, and your backend decides the meaning of those inputs. Pushpin could perhaps be awkwardly described as “a proxy server that enables web services to delegate the handling of realtime push primitives”.

On a practical level, there are many benefits to Pushpin that you don’t see anywhere else:

Scalability

Pushpin is horizontally scalable. Instances don’t talk to each other, and sticky routing is not needed. Backends must publish data to all instances to ensure clients connected to any instance will receive the data. Most of the backend libraries support configuring more than one Pushpin instance, so that a single publish call will send data to multiple instances at once.

Optionally, ZeroMQ PUB/SUB can be used to send data to Pushpin instead of using HTTP POST. When this method is used, subscription information is forwarded to each publisher, such that data will only be published to instances that have listeners.

As for vertical scalability, Pushpin has been tested with up to 1 million concurrent connections running on a single DigitalOcean droplet with 8 CPU cores. In practice, you may want to plan for fewer connections per instance, depending on your throughput. The new connection accept rate is about 800/sec (though this also depends on the speed of your backend), and the message throughput is about 8,000/sec. The important thing is that Pushpin is horizontally scalable which is effectively limitless.

Fault-tolerance

Pushpin was designed to be reliable enough to front an entire web service if necessary. In order to reduce the risk of bugs affecting non-push traffic, Pushpin is split into multiple processes. The proxy capability is handled by pushpin-proxy, while the publish-subscribe capability is handled by pushpin-handler. The idea is that pushpin-proxy should be stable and rarely modified, while active feature development should primarily take place in pushpin-handler. If pushpin-handler ever fails, regular traffic will continue to flow.

See Multiple processes.

Support

If you have a question about Pushpin, feel free to post on the community forum:

Other resources:

Commercial support is provided by Fastly. Please contact support@fastly.com.

License

Pushpin is licensed under the Apache License, Version 2.0. See the LICENSE file.