> Current best practice is to use SSL for all communication between your own servers anyway, so there's no gain.

I've never heard this. Who does this? Everyone I know of either just naively relies on the privacy of NAT-style non-routability in something like an AWS VPC, or, if they're more paranoid (or their provider has no private-networking feature, or they need HIPAA compliance, or whatever), uses IPSec—which is, happily, exactly the proper use-case for IPSec.

(Unless what you actually mean is requests between separately-maintained microservices that are supposed to treat one-another as if they were produced by third parties, like AWS strives to do. But the "your machines" makes me doubt that; you wouldn't think of those other machines as "yours" in that case.)

> From using the web, I don't think this is done anymore. In fact it seems to be the opposite - foo1.app.com, foo2.app.com seems to be the trend.

Green-field applications, no matter the size, are usually deployed to separate subdomains, yes. For long-term maintenance, though, nothing beats being able to just mount a new backend (probably written in a different language, even) on top of your legacy app's /admin/ or whatever else. It's effectively about patching a resource space with new backends to handle parts of it, without having to touch the legacy code to get it proxying to the new server. Businesses that embrace the "cool URLs don't change" philosophy—for example, newspapers who want their heavily-linked-to story pages accessible forever—take this approach all the time. Their web servers are rats' nests of routing rules to different backends, to make everything seem, from outward appearance, to be the same as it always was, even when everything is now in the CMS-of-the-week.

The other place this happens is API servers—you might want /1.1/ and /2.0/, or even /feeds and /emotes, going to different clusters. (If you're doing that in the path instead of using content negotiation.) That kind of business-policy-level routing is not the rightful domain of a load balancer, even if haproxy et al can be configured to do it; you want your load balancers to be dumb stateless infrastructure components, and your web servers to be maintained and configured and updated as part of the service you're deploying.

> If you use node and nginx and apache then any exploit that hits any of those 3 will hit you.

There are a bunch of clever things that genuine, battle-tested "web servers" do that "application web servers" don't. Preventing Slowloris attacks, for example—it's something every HTTP server would do in an ideal world, but since it complicates the code and prevents streaming parsing, you really only want to handle it once (by buffering requests) at the input end. There are umpteen other such attacks that web servers just abstract away. Even with, say, Erlang's "battle-tested" reputation, I wouldn't trust it sitting on the open web without nginx or something else in front.

Usually, though, your load balancer is also a "web server"... if SSL has been terminated there so that it can actually parse the requests and responses. This tends to be why some people actually chain haproxy -> nginx -> their app server: they put haproxy in dumb TCP load-balancing mode, while nginx terminates SSL and thus gets to be the "web server."