BEAM, Cowboy and Plug

How does BEAM work? What does cowboy do exactly? and what exactly is Plug?

I still don’t have a clarity between these things. Can someone explain it please?

BEAM is the acronym of Bogdan/Björn’s Erlang Virtual Machine and is one of the implementation of Erlang VM (others are JAM, Lumen, Enigma, ErlangRT, AtomVM). This one is most popular one, and is the Erlang VM (reference implementation). Think of it as an OpenJVM vs Dalvik/OracleJVM/etc. in Java world.

Cowboy is HTTP(S) and WebSocket server, think of it like Glassfish/Jetty/Tomcat in Java world, or WEBrick/Puma/Unicorn in Ruby world.

Plug is common interface for HTTP servers. This is more like Rack in Ruby universe.

So in short:

  • BEAM is VM
  • Cowboy is HTTP(S) server implementation
  • Plug is library for providing common API to different HTTP(S) servers (currently only server supported officially is Cowboy, but in theory you can use any other as long as you create adapter).
12 Likes

can you please explain how these three things work together? like what runs where?

  • The BEAM is needed to run any Erlang/Elixir application.
  • Cowboy is an Erlang application… (It would be the A in LAMP)
  • Plug is just a library, that can be used by application.
2 Likes

Thanks, that gave me a better idea

As per Plug documentation

Plug is:

  1. A specification for composable modules between web applications
  2. Connection adapters for different web servers in the Erlang VM

What does this mean?

A plug is just a function that accepts a Plug.Conn.t and a configuration “thing” (I just want to say “object” but Elixir is not object oriented so I don’t know how to name it. A “term”?) That function can be wrapped in a separate module (something like a functor if you are familiar with C++).

If a function accepts the same arguments as above, changes the conn a little bit, and delegates the job to a plug, then the function is another plug.

In this way, you can chain plugs together, with each plug handles only a small task in the whole HTTP request handling, and the result of the chaining is a big plug. That’s what “composable” means. For example, in a conventional Phoenix application, you can find Plug.RequestId which attaches a unique random string to each request for the DevOps team to trace every request; Plug.Parsers for parsing the query strings and request bodies; Plug.MethodOverride for overriding the method according to the _method param; Plug.Session for loading sessions, and finally the MyApp.Router for dispatching each request to the correct controller action. (I omitted a few plugs) These plugs combine together into a single big plug.

If an Erlang/Elixir web server can chew and spit Plug.Conn.t, it can run any plug-based web application such as Phoenix application. If it can’t, well, probably someone will write or has already written an adapter for that server. So you can think of Plug as an adapter between your web application and the plug-aware web server, and that’s what “Connection adapters” mean.

4 Likes

@shijith.k I’ve actually wrote a small deep-dive into Plug and Cowboy and how they work under the hood which you can read here hope it helps!

3 Likes