Embedded vs. External Web Servers

Firstly, Twitter’s 140 character limit is too short for sharing thoughts longer than one or two sentences. I regularly question my development practices and sharing my internal debates is a good way for me to analyze the arguments, but I tend to sound incoherent when I use Twitter for that purpose. What better place to do so than on this blog? Expect to see more frequent, albeit shorter, posts like this one from now on. Now on to the post.

Recently I have been examining the different models of web application architecture at the server level. I’m experimenting with my own web “framework” (API glue really) for Rust, and I notice some very different approaches in Rust web development than in some other languages. Rust frameworks like Iron provide the HTTP server as a library, and your web application runs the server in-process. This is quite different than the classic “web server + CGI” model that so many frameworks were designed around in the last 20 years.

There’s really two main models that you see in the wild. For lack of existing terms (this stuff is hard to search for), I’m calling them “embedded servers” and “external servers”. So we are on the same page, here’s what I understand the differences to be:

With an embedded server:

With an external server:

Certain programming languages and frameworks seem to have a disposition to one or the other of these models. PHP was originally designed to be used with CGI (Common Gateway Interface) behind a web server like Apache, very much the external model. Node.js was designed from the ground up around the embedded model. Java’s servlet API is focused on the external model, although running a Java web server embedded into your app is becoming pretty common.

But which model is better? Both probably have their uses, so wrestling over which is better is silly. A better question is: what are the pros and cons of each?

Embedded server pros:

Embedded server cons:

External server pros:

External server cons:

I think people tend to exaggerate the overhead of communicating with an external server, especially if you’re using something like FastCGI or ISAPI which perform very well. Even so, the bottleneck is almost always your application code and not the HTTP server. Unless you are writing a performance-critical, timing-sensitive web service (which you probably are not), I don’t find the performance argument for an embedded server very convincing.

The embedded model definitely makes sense for programs with a web-based interface (routers, daemons, etc.), as setting up a web server in addition to your software seems like overkill when the web interface isn’t the product itself. For web applications though, requiring an external server seems like a normal requirement (maybe even a feature of choice), but maybe it’s because we’re used to it by now.

This isn’t conclusive evidence for one way or another, but I am currently very interested in making the external model easier to do in Rust. I’m also curious to hear what other people think about this. Maybe I don’t hang around the right people, but this seems to be a topic that is under-discussed and everyone just “assumes” different things.


Let me know what you think in the comments below. Remember to keep it civil!

Subscribe to this thread