Self-hosted service
Accenture/reactive-interaction-gateway avatar
Accenture/reactive-interaction-gateway

Reactive Interaction Gateway: the four request paths and the Docker build behind them

Create low-latency, interactive user experiences for stateless microservices.

602 stars68 forksElixirApache-2.0

At a glance

What is it?
RIG is an Elixir gateway that sits between a browser and stateless backend services, routing requests over HTTP while pushing backend events back to clients through Kafka, NATS or Kinesis. Its release tags stop in 2022 even though commits continued into 2026.
Who is it for?
RIG fits teams that already run a message broker and want subscription driven push to browsers without touching frontend code, and it fits poorly for teams with no broker, for mobile apps with no persistent connection, or for anyone who cannot accept an Elixir runtime in the request path.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Elixir, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap RIG was built to close

The Reactive Interaction Gateway describes itself as the glue between your client and your backend, and the interesting part is the failure mode it removes. A stateless service behind an HTTP API cannot push a change to a browser on its own. The usual answer is polling: the frontend asks again and again, waits, and repeats. The README frames RIG as the alternative to that loop, picking up backend events and forwarding them to clients based on subscriptions so the frontend becomes reactive.

That positioning also explains the project's insistence on standards and replaceability. The documentation claims RIG does not leak into your application, meaning no libraries or SDKs are required on the client side. For an engineering team, this is the whole pitch: you can remove the gateway later and the browser code does not need rewriting. For a team that has already embedded a vendor client library in every frontend, the cost of switching is higher than the cost of installing RIG.

Four ways a request can cross the gateway

The gateway exposes four distinct request handling modes, and the distinction between them is where the real design lives.

Synchronous proxying is the plain case: RIG forwards the request to an HTTP endpoint of a backend service, waits for the response and sends it back to the client. This is the mode that lets the gateway slot into an existing architecture with no behaviour change.

Asynchronous fire and forget converts the HTTP request into a message and forwards it through Kafka, NATS or Amazon Kinesis, with no response expected. Then there are the two hybrid modes, both described as pseudo-synchronous. In the first, the request reaches the backend synchronously over HTTP, but the answer is retrieved by listening on Kafka or NATS and pushed into the still open HTTP connection to the frontend. In the second, the request itself travels asynchronously over Kafka or NATS and the response comes back the same listening way. Both hybrids trade a held open connection for broker round trips, which is useful when the backend work is slow but the browser can tolerate waiting on one request.

Building the image with pinned Elixir and Erlang versions

The repository ships a multi stage Dockerfile that is also the clearest statement of the runtime constraints. The build stage starts from an Elixir 1.11.3 Alpine image, installs the C toolchain, then fetches and compiles the dependencies before producing a Distillery release. The runtime stage drops to a plain Erlang 23 Alpine image and copies only the built release across.

dockerfile
FROM elixir:1.11.3-alpine as build
RUN apk add --no-cache make gcc g++
ENV MIX_ENV=prod
RUN mix deps.get && mix deps.compile && mix deps.clean mime --build
RUN mix compile
RUN mix distillery.release
FROM erlang:23-alpine

Two things follow from that file. First, the toolchain is old and deliberately pinned, so a fresh build inherits the versions the project chose rather than whatever is current. Second, the release is produced by Distillery, which the acknowledgements list among the projects RIG builds on, and the runtime image contains no Elixir toolchain at all. If your organisation requires images built on a supported base, that patching work sits with you. The getting started tutorial referenced from the project documentation uses Docker, and the deployment directory holds the Kubernetes instructions, including a Helm chart published alongside the application.

Two exposed ports and a non-root runtime user

The runtime image creates a dedicated group and user, copies the release into the working directory, and switches to that unprivileged account before starting the process. It then declares two ports, 4000 and 4010, and starts the release in the foreground under signal traps so that container stop signals are handled cleanly.

dockerfile
RUN addgroup -S rig -g 1000 && adduser -S rig -G rig --uid 1000
EXPOSE 4000
EXPOSE 4010
CMD trap exit INT; trap exit TERM; /opt/sites/rig/bin/rig foreground & wait

The two ports are not interchangeable. The Dockerfile labels 4000 as the proxy and 4010 as the internal APIs, so traffic aimed at one of them is not the traffic aimed at the other. When you place RIG behind a load balancer or inside a Kubernetes Service, that distinction decides which port maps to the public listener and which stays internal. The repository also carries monitoring, performance_tests, integration_tests and smoke_tests directories, which tells you the project expects its own behaviour to be exercised rather than assumed.

Subscription driven push without a client SDK

The forward direction has the same two flavours as the request direction. Backend events can be picked up asynchronously, using Kafka, NATS or Kinesis, or synchronously, for teams that do not want to run a broker at all. The synchronous option is the interesting trade: it avoids operating Kafka or a comparable system, at the cost of giving up the decoupled pipeline that makes the asynchronous mode attractive in the first place.

The examples directory shows the client side of this. It contains demo pages for server sent events and for WebSocket style channels, including variants that use a JWT extractor, variants that read a simple extractor, and a staticServer.js file, which suggests the demos are served locally for experimentation. The repository topics list server-sent-events, live-data, unidirectional-data-flow and cloudevents-schema, and the examples directory includes an extractor.json, so event payloads are passed through a schema check rather than forwarded blindly. The README also points to an API gateway example, which is the closest thing in the tree to a second product shape for the same code.

Release tags from 2022, commits that run into 2026

The version history needs reading carefully. The recent releases list shows 3.0.0 dated 2022-08-12, along with 2.1.3 and the matching Helm chart from the same day, with the chart published a few minutes before the application release. The repository is not archived, and the last push was on 2026-04-16. So the tags tell you where the project published versions, and the push date tells you that work continued on master afterwards. What it does not tell you is whether the 2026 commits are cutting a release, backporting fixes or exploring new directions, because the tag list stops at 2022.

That gap is the practical upgrade cost. Anyone pinning 3.0.0 from 2022 gets code that predates four years of commits; anyone tracking master gets untagged changes and takes on the risk of the tree moving under them. The documentation site, the FAQ and the developer guide are the practical escape hatches, since the README itself is a summary that defers most detail to that site.

Where RIG is the wrong tool

The strongest argument against RIG is the one the README makes in the other direction: a gateway adds a hop and a runtime. A team whose backend already answers plain HTTP requests and whose frontend can poll responsibly has no reason to introduce Kafka or NATS into the request path just to avoid a timer in JavaScript.

The hybrid modes also carry a cost that the documentation describes plainly. Both pseudo-synchronous paths keep an HTTP connection open to the frontend while the answer arrives over a broker topic. That is fine for a browser that is going to sit on the page anyway, and awkward for a client that cannot hold a connection, or for a fleet of short lived clients where every held open socket is a resource you have to budget. The gateway is also written in Elixir on Erlang, so operational familiarity matters, and the project dependencies named in the acknowledgements, Phoenix Framework, Brod and Distillery, are the pieces that determine how hard the on-call rotation is.

Against a plain reverse proxy and a hand written event stream

A conventional reverse proxy sits in the same position and does less. It forwards a request to an upstream service and returns the response, which is exactly RIG's synchronous mode, and it has no way to decide that one browser should receive an event that another browser should not, because subscription matching needs a broker and a filtering layer. The difference is not speed; it is that RIG can route a single request to a backend, and route the resulting event back to a specific client, over the same infrastructure.

The other alternative is writing the push yourself: a WebSocket or server sent events endpoint inside each service, plus a shared bus for fan out. That approach keeps the gateway out of the system, but it pushes broker management, schema validation and client connection handling into every service that wants to publish. RIG centralises that work in one Elixir process, and accepts the corresponding cost of a component that must be operated, patched and replaced.

Editorial conclusion

RIG fits teams that already run a message broker and want subscription driven push to browsers without touching frontend code, and it fits poorly for teams with no broker, for mobile apps with no persistent connection, or for anyone who cannot accept an Elixir runtime in the request path. Before adopting it, check whether the version you plan to run matches the 3.0.0 tag from 2022 or the newer commits on master, and read the getting started tutorial in the project documentation to confirm the two exposed ports fit your network layout.

Frequently asked questions

Which message brokers can Reactive Interaction Gateway use?

The README states that RIG can pick up backend events and forward them to clients asynchronously using Kafka, Nats or Kinesis, and the same three options are listed for fire and forget request forwarding. If you prefer not to run a broker, it also describes a synchronous mode for event pickup.

Does Reactive Interaction Gateway require a client library or SDK in the frontend?

No. The README says RIG does not leak into your application and that no libraries or SDKs are required, with the aim of being easy to integrate and easy to replace.

How do I deploy Reactive Interaction Gateway to Kubernetes?

The README points to the Kubernetes deployment instructions in the repository's deployment directory, and the release history shows a Helm chart published as reactive-interaction-gateway-helm-v2-2.1.3 in August 2022. The getting started tutorial on the documentation site covers a Docker based walkthrough.

Official sources

  1. Accenture/reactive-interaction-gateway on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/accenture-reactive-interaction-gateway.svg)](https://hysenlabs.com/projects/accenture-reactive-interaction-gateway)

Was this useful?