Simpler alternative to phoenix for web-hooks endpoint?

I am building a simple multi-tenant telegram-bot solution.

Telegram bots simply exchange json messages via https.

All I require is a simple endpoint for web-hooks

httpoison works fine for sending http-responses

What would you suggest as an alternative to Pheonix in this scenario?

In C# / , I would have used a HTTPListner for this.


Phoenix is just a set of helpers on Plug, and almost every library for web hosting anything is built on Plug as well, there is no reason not to use Phoenix as you can use as much or as little of it as you want. :slight_smile:

You can of course just use Plug straight too, it even has a router. ^.^


Possibly plug, but have just found this as well:


Sounds like Plug is exactly what you want. The only “simpler” option would be to use a web server directly, such as cowboy if you’re wanting to keep deps to an absolute minimum. Also, as @OvermindDL1said Phoenix would serve this purpose well so don’t count it out immediately, but it sounds like a couple plugs and a Plug.Router is a perfect fit for you, so I would start there.


raxx was a perfect fit for a simple web-hook server

  1. Zero magic under the hood
  2. I could fully understand all the code - it’s a very small code base.
  3. Had both cowboy and elli up and running in no time

You should give it a try :wink:

1 Like

Glad it working well for you! To be clear, since this is a Phoenix alternative discussion, what “zero magic” would you say this uses instead of phoenix or plug? From the readme:

To use Raxx provide an app: A module that implements handle_request/2, taking a request and config as arguments and return a respone map

This sounds just like the basic plug contract, where you define a call/2 function that accepts the connection and options, so not more or less magical.

It’s also worth noting that José back in 2012 was looking at the current state of Rack and the modern web and saw serious issues with its design:

I’m not familiar with the Raxx codebase, but I see it takes inspiration from Rack, so those posts concerns are worth considering if adopting a rack-based api.


I believe this is a perfect fit for something as simple / trivial as say a webhook endpoint or a REST-API endpoint, which is the use-case I have here.

The key here was to find something simple, that I could understand in total.

I will give Plug a second try though.

1 Like

I was looking for something similar so I started a quick little playground project with Plug/Cowboy. It’s just me experimenting with some simple routes, and controller like functions. Plug makes it very straightforward and easy to understand. You can check it out here:

1 Like

Which tutorials have you looked at (if any)?

I find the apidox for various modules to be quite good … but they don’t give you a system-level overview that is often so important to getting moving with confidence. is pretty decent, and there are a number of other tutorial/walkthrough content (though often pay-to-access) available online.

Plug itself is pretty simple and easy to use (and also flexible and performant, which is a semi-magic combination :slight_smile: ), but to get going I found having that “system overview” beyond just the apidox to be crucial.


Just a quick comment on this one because I believe it to be a fallacy.

  • The conn object has reference to processes meaning it has scope to do substantially more.
  • handle_request in raxx is treated as a pure function which means that testing does not require any addition boiler plate
    assert %{status: 200} == %{path: [], method: :GET} |> MyApp.handle_request(nil)
  • Never know what counts as magic but the above two points make reasoning about handle_request much easier.
  • I was able to easily implement adapters for three webservers to raxx. cowboy, elli and ace(my own webserver), as far as I am aware there are no widely used adapters for plug and any server other than cowboy. In my opinion this was a result of reduced complexity in the interface.

This article is worth mentioning because I knew about it before starting on raxx.

In summary rack is a model of requests and responses, plug a model of connections.

  • Handling websockets, large file uploads are better considered as connections. i.e. plug
  • Working with API’s or where whole request and response easily fit in memory best modeled as request - response cycle i.e. raxx

At the moment I find myself writing more projects of the second kind. But I would not try and implement phoenix presence in the raxx model. (At least not yet, raxx does have support for server sent events which is an extension to the rack model but this is experimental for now)


I don’t find it has much to do with dataset size, but rather being able to model the flow the request handling. This is the motivation behind the (imho, bane) of “middleware” in the more typical frameworks in common use.

The approach Plug provides is for me more about composability than dataset size: one can quickly and cleanly create one or more “pipelines” that can do whatever is deemed necessary (authentication and sessions; CSRF; logging; …) separate from each other and, most importantly, the response. And when there are multiple render targets (e.g. HTML vs JS), one can easily set up pipelines for each sharing the common functions as plugs between them … but only what is needed and appropriate (avoiding “one size fits all”).

For me, that is far far far more important than data set size, and something that plug makes dead simple, merely by realizing that what other frameworks see as “middle”-ware should be “upfront, composable”-ware. :wink:


You might also be interested that there is a layer on top of raxx, tokumei, (Work in progress). It trades adding a few macros (magic) for a bit more convenience, routing helpers and automatic discovery of templates

1 Like

I don’t know if you have become any more familiar with the codebase or project since posting this. I see people are still finding Raxx from this thread so thought I would comment further.

Raxx has evolved significantly over the last few months. It now has a solution that will handle streaming and means the concerns raised in jose’s post are not applicable. It manages this while using only pure callbacks. This is probably the most important reason for it’s simplicity. This pattern of pure callbacks will be recognisable to anyone who has used GenServer.

A detailed overview for using Raxx in different situations can be found in the 1.0.0 release candidate README