Varnish FetchError http first read error: -1 11 (Resource temporarily unavailable)

Just like the Straight insufficient bytes error, this is another error you can see in your varnishlogs.

It looks like this.

11 VCL_return   c hash
11 VCL_call     c pass pass
11 FetchError   c http first read error: -1 11 (Resource temporarily unavailable)
11 VCL_call     c error deliver
11 VCL_call     c deliver deliver
11 TxProtocol   c HTTP/1.1
11 TxStatus     c 503
11 TxResponse   c Service Unavailable
11 TxHeader     c Content-Type: text/html; charset=utf-8
11 TxHeader     c Content-Length: 686
11 TxHeader     c Accept-Ranges: bytes
11 TxHeader     c Age: 15
11 TxHeader     c Connection: close
11 TxHeader     c x-Cache: uncached
11 TxHeader     c x-Hits: 0

What’s happening#

The error “HTTP first read error” can indicate that your Varnish config is not waiting long enough for the backend to respond. A default backend definition in Varnish will wait for 5 seconds for a “first byte” from the upstream. If it doesn’t respond in that time, it’ll close the connection and throw an HTTP 503 error.

The quick fix (but not the best)#

Modify your backend definition to look like this, to allow for longer waiting responses. It’s especially the .first_byte_timeout option that will make the difference.

backend my_backend {
  .host                   = "127.0.0.1";
  .port                   = "80";

  # How long to wait before we receive a first byte from our backend?
  .first_byte_timeout     = 300s;

  # How long to wait for a backend connection?
  .connect_timeout        = 3s;

  # How long to wait between bytes received from our backend?
  .between_bytes_timeout  = 10s;
}

The example above will wait for 300 seconds (= 5 minutes) for the backend to respond with the first byte.

The error will mostly pop-up when a POST is made to the server, but the request is too slow to be processed and is causing the server to take longer to send a reply to the request. Increasing the upstream timeouts can help. But you may not want to do this for all requests.

Setting a longer timeout for certain pages#

In case you don’t want longer timeouts for all pages, it’s a good idea to configure 2 backends; one that you can use for “normal” situations and one for requests that you know take longer. For instance, a config like this might help you. You define a second backend, with longer timeouts and in your Varnish VCL, you set logic for switching between these backends.

backend my_backend_normal {
  .host                   = "127.0.0.1";
  .port                   = "80";
}

backend my_backend_longwait {
  .host                   = "127.0.0.1";
  .port                   = "80";

  # How long to wait before we receive a first byte from our backend?
  .first_byte_timeout     = 300s;

  # How long to wait for a backend connection?
  .connect_timeout        = 3s;

  # How long to wait between bytes received from our backend?
  .between_bytes_timeout  = 10s;
}

sub vcl_recv {
  # Set the default backend server
  set req.backend = my_backend_normal;

  # Set the backend for POST requests
  if (req.request == "POST") {
    set req.backend = my_backend_longwait;
  }

  # Or set a longer-waiting backend for specific URL schemes
  if (req.url ~ "^/some/vary/long/page$") {
    set req.backend = my_backend_longwait;
  }

  ...
}

This gives you the benefit of having smaller timeouts for “normal” pages, and selective longer timeouts for pages that you know will take longer to respond.