Skip to content

Follow curl: Enable setNoDelay() / TCP_NODELAY by default on HTTP(S) 1.x #34185

Closed
@voxpelli

Description

@voxpelli

Prior art

Issues

This has been discussed before without any conclusion:

Relatedly #906 and the discussion there has been mentioned:

Commits

The setNoDelay() option was originally introduced in 2009 in e0ec003 and was shipped in v0.1.12

Wider context

curl

In 2016 curl changed it's behavior from being like the one in Node.js to instead be setting TCP_NODELAY by default. See curl/curl@4732ca5 which was released in v7.60.2.

Motivation from commit:

After a few wasted hours hunting down the reason for slowness during a TLS handshake that turned out to be because of TCP_NODELAY not being set, I think we have enough motivation to toggle the default for this option. We now enable TCP_NODELAY by default and allow applications to switch it off.

npm modules

agentkeepalive

The agentkeepalive module, with ≈3.5 million weekly downloads, pushes its non-configurable default of socket.setNoDelay(true) as one of its major benefits.

It was added in node-modules/agentkeepalive@c92f5b5 and references a Scaling node.js to 100k concurrent connections! blog post to explain it.

Used by eg. eggjs/egg, cnpm/cnpmjs.org, pubnub/javascript, googlemaps/google-maps-services-js, node-modules/urllib

superagent

In 2017 the superagent module, also with ≈3.5 million weekly downloads, merged ladjs/superagent#1240 and made socket.setNoDelay(true) its non-configurable default, largely arguing that there was no need for any buffering.

Other npm modules

Many modules relies on the default behaviour of Node.js, and thus does not disable any delay by default.

A quick glance puts all of these in that category, none of them directly calls setNoDelay (though they could eg. use something like the agentkeepalive module): axios, bent, got, node-fetch, request, unfetch

Documentation

The Node.js documentation of setNoDelay was recently updated: #31541

Before that update, my perception is that many believed that Nagle's algorithm wasn't enabled by defaults, as proved by eg. the conversation in superagent: ladjs/superagent#1240

Proposed change

To make TCP_NODELAY / setNoDelay the default for HTTP(S) 1.x + maybe introduce a setDelay() method to disable it.

Probably in a new major version, as it can be a breaking change in some contexts.

Why

I believe that the expectations has changed since setNoDelay was introduced in 2009.

With eg. curl now setting it by default I believe most expects TCP_NODELAY / setNoDelay to be set by default and thus Nagle's algorithm to be disabled by default.

The confusion the current default seems to make in issues like ladjs/superagent#1240, especially before #31541, supports that.

Also: As TCP_NODELAY / Nagle's algorithm is implemented at an OS level this can also have a minor added benefit of improved cross-platform behavior, as no platform will add a delay.

Benefits

  • Better comply with general expectations among developers
  • Move with the times and in sync with other major players like curl
  • In some cases better performance due to no delay. Especially so in real time scenarios.

Downsides

  • Possibly increased bandwidth use
  • Possibly decreased performance due to bandwidth saturation
  • As any change of a default on this level, it breaks the expectations of those who knowingly wants the current default behaviour.

My background

I have no expertise in the implementation of Nagle's algorithm or the TCP-stack in general, though I became intrigued by this and did my research and through that research I found that most were either confused by this or had already changed the default for this.

Comments, suggestions, feedback and link to other discussions would be most helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    netIssues and PRs related to the net subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions