Help Making a Design Choice, AJAX vs. Websocket

Phoenix really shines because of its websockets, not using them would be strange IMHO

1 Like

i’d still recommend AJAX. probably no external API you are going to use will be a websocket one.

but it sounds a little strange to me. how vuejs on your website communicates to your phoenix application doesn’t really have anything to do with “modules accessing the net”, so i’m a bit confused. are you not going to run the phoenix application on some server? the phoenix app and the web browser will be on the same host always?


The Phoenix app will run locally. The app will eventually make requests/responses to remote websites & APIs. But all processing for now, is planned to be done locally.

Eventually I can see it grow to an app that some processing is handed off to a node network. So, my primary question is should I architect it right now for that possibility? And if that’s the case is Websockets the better tool to use?

for requests to external websites and apis websockets won’t be the right tool.

for your vue app to communicate with your phoenix app, they might. using ajax with a json api will give you a lot more tutorials and best practises, though, as this is the much more common/older way of doing things.

what kind of app are you building? the case would be different for a chat app, for example. ajax has to be initiated from your vue app, which means it has to ask for new data. with websockets, the phoenix app can more easily tell your vue app that there is new data, i.e. a chat message.

I’d say it depends on the kind of information you want to send back and forth.

Neither Websockets nor AJAX are complex in their basic usage. The main difference between the two is that a websocket connection is a persistent client<->server connection, where (therefore) both sides can at any time initiate a new request to the other, whereas AJAX involves setting up (and afterwards closing again) a new connection that works client->server. This means that with AJAX, only the client can initiate contact.

If therefore your application works with data that the server creates/receives and should then send to the client quickly, then websockets are definitely better. The AJAX alternative to handle this would be short-polling or long-polling, which are basically ‘hacks’ that allow you to ‘fake’ bidirectional communication because your client will keep on asking the server the ‘do you have something new yet?’ question until the server responds with something new.

Both because AJAX involves setting up/tearing down a connection each time, as well as requiring techniques like longpolling to handle bidirectional traffic, AJAX is (significantly!) slower than using websockets.

Still, depending on what your application does exactly, having a delay of a few seconds before a new message arrives because long-polling is used might not be noticeable.

However, Phoenix (and its JS clientside websockets-wrapper) abstracts the difficulties of how websockets internally work, so I definitely would advise using them for your application.


@Qqwy: Good answer! I want to write something similar in my words …

Basically AJAX is good when you are only fetching data from server like using JSON REST API (for example for CMS front page).

WebSocket is required for example if you want to create fast client-server chat application.

Another good example for both Elixir and Phoenix WebSocket is update graph. Simply Elixir could have a process in background that sends event through Websocket, so after data is changed client gets info about it as soon as possible. Here I also recommend new Registry Elixir API that is awesome in combination with Phoenix WebSocket connection. I found a good example for PubSub with WebSocket using this API.

1 Like

I actually tackled the same problem as you and came to the conclusion that websockets are the best.

  1. It’s a vue app that I am in control of - no compatibility issues since it’s going to be used within the org.
  2. Vue2 got rid of $http in favor of using external libraries - this made me decide to use phoenix sockets, since either way I’m going to have to use an external library
  3. Vuex abstracts away the actual API calls - if I end up hating websockets, I can exchange the calls in my vuex actions to make AJAX calls instead
  4. sockets are vogue and hip

I implore you to check out vuex, which is just as palatable as vue. Basically what I did is in Application.vue, I set up the socket and registered the events I wanted to listen for. For the receive event, I called a vuex action that would set the state.

The websockets seemed more approachable as someone who didn’t have experience with Vue or Elixir/Phoenix.

If I get a chance, I’ll post my implementation so maybe you can get some ideas from it.

1 Like

Websockets. AJAX requires setting up and tearing down the connections on every request. Long polling can mitigate latency in ‘receiving’ a bit, but websocket is the only way to minimize latency all the time in both directions.

Phoenix Channels (it’s implementation of websockets) are so simple to use, ask if you have any questions. :slight_smile:

SImplicity of use is simplicity of documentation too. :slight_smile:

And for note, AJAX is just normal http requests using the normal http ways including all the expensive setup and all, but it can be done in a single line of javascript where channels take a couple of easy lines. If you know how to build normal web requests, you already know AJAX then, except you return JSON instead of HTML. ^.^


If it is for real-time communication where latency is important then websockets blow AJAX away. And I’ve seen a few API’s use websockets via tokens without issue, usually not worth it in most languages to set up unless the real-time need is necessary, though with Elixir it is so easy to websocket there is no reason not to anyway.

If they are rare polling requests then external API’s will not. However external API’s mandate whatever they mandate, that has nothing to do what-so-ever with using websockets for their own front-end.

OhgodNo, jsonapi needs to die, if you are going to vote for that then go for GraphQL then. Speaking of, you can use GraphQL over websockets too.

Exactly what @Qqwy said! ^.^

And what @Eiji said!


i never said jsonapi, i said “a json api” as in an api that communicates in json.

i still believe ajax with json might be a good choice for op, as they seem to be learning. read up on best practices about building a rest api and connecting that to a frontend and you pretty much have a step by step guide.

if you want to build the websocket / channels integration, you need to invent a lot yourself. the tools are all there, but best practices not so much, i think.

technically, you are all correct. websockets / channels will outperform ajax. i was looking more at the learning and documentation side.

1 Like

Ah I see most people reference actual JSON API, sorry for the quick reaction. ^.^

In that case yeah, a simple JSON interface, or GraphQL (which returns json) would be great.

Hmmm such as? Take GraphQL over websockets, there are libraries out that simplify that trivially. Or just make the raw channel calls, which is simple json.

Thanks for all the input.

If I go down the Websocket route, is there any disadvantage to using the abstraction of Websockets for the VueJS side? Or am I just adding complexity? (I know nothing about either currently.)

Technically you would be using a Phoenix channel, which only uses web sockets if they are available, so you would want to stick with the Phoenix API - at least that is my understanding.

…On the Phoenix side… but I still needs something on the VueJS side, I believe??

I’ve never used nor even heard of, so I could not say. ^.^
The Phoenix stock javascript is dead simple to use though. :slight_smile:

Just make the calls via any normal way you would in vuejs, you could even sprinkle it around in the components directly (though putting them in another class and wrapping them lets you easily change it in the future, like to GraphQL over phoenix websockets or something). :slight_smile:

Ok, when you are using “WebSockets” - but when you are using Phoenix channels (which by default use a WebSocket) you should use phoenix.js, socket.js. (Joining Channels)

The Phoenix socket abstraction is by default backed by a WebSocket - and you get a channel from the Phoenix socket.

The default transport mechanism is via WebSockets which will fall back to LongPolling if WebSockets are not available.


Phoenix holds a single connection to the server and multiplexes your channel sockets over that one connection.


Such as “Which channel do I join”?, “What message do I send to ask for a list of data?”, “What message do I send to ask for a specific resource?”, “What message do I send to create/update a resource?”, “How do I handle validation-/authorization-/other kinds of errors?” With a basic REST API, all of that is pretty clear. You can even have phoenix generate the basics for you. With channels I’m not aware of any established best practices for that, which I think is a big, big disadvantage WHEN LEARNING.

GraphQL is really cool, I’m using it myself. However, if you’re learning Phoenix and Vue, adding GraphQL will add another new thing you need to learn. And making it work with websockets/channels is yet another non-standard thing. There’s Absinthe.Plug, but I don’t know of an out of the box solution for GraphQL over channels.

1 Like

There’s Absinthe.Plug, but I don’t know of an out of the box solution for GraphQL over channels.

I think graphql subscriptions (graphql over websocket) will be available in absinthe sometime soon [0][1]. Not sure if they are intended to complement or replace phoenix channels, though.


Whatever your want, that is your creation. ^.^

Whatever your want, that is also your creation. ^.^

Also whatever your want, that is your creation. ^.^

Ditto, sensing a pattern yet? :wink:

Not really, same decisions with rest. Names of endpoints, connections, what data can be served, how to query for it, etc… etc… etc… :wink:

That template is an example, it is not a full REST endpoint, it is for interacting with only a single schema, and I near never see just single schema’s asked for or queried for.

Phoenix has default templates for those too, but again it all depends on just ‘what’ you are trying to accomplish.

GraphQL is just a query, think SQL, but for JSON, still very succinct and simple, it is not bound to any specific transport medium, only that GraphQL is a request and it returns JSON. You can use it over endpoints, channels, raw TCP, whatever. And GraphQL is quite used, there is plenty of documentation on it out there. Using it with channels all I did was just have a single message that I named “request” and I just take the string from it and call absinthe with it and return the results, it is the same thing you do if it is on an endpoint (though it has a plug that can save you that step, though piddly a step it is).

GraphQL Subscriptions are a new GraphQL thing (not in absinthe, they are new in general), it just lets you basically ‘register’ to a query and you get the response like normal, except you keep getting responses again and again as it changes. ^.^

That would be trivial to push over websockets as well.

1 Like

This is where I see the biggest danger with GraphQL - people deciding to simply pull an OData and expose the persistence schema all the way up to the front end, creating a franken-system, architectural and maintenance nightmare where the frontend is deeply coupled into every little aspect of the persistence layer.

GraphQL can be a big plus provided its schema is designed around consumer-driven contracts but I imagine quite often that is seen as just too much effort - and ultimately laziness will drive people to head for the next button that promises to generate a GraphQL application to expose the database as is.

This is what so many do with REST yeah…

It really should not be done with GraphQL, it is more of RPC, a function call to acquire data and get a response back, except of course you can state in what format you want the data back in. I just add a new absinthe schema/object when I need to call a new ‘function’ to get some data that I’ve not needed yet. Two of them do not even access the database at all. ^.^