Search code examples
node.jsamazon-web-servicesaws-fargatefastifyhealth-check

ECS Fargate health checks are failing after migrating to fastify


I have an SSR server. It used to run on ExpressJS. For performance reasons, I migrated it to Fastify. Now, my health checks keep on failing and therefore my containers get stopped.

My CloudFormation defines health checks as:

  HealthCheckPath:
    Type: String
    Default: /categories

It works fine for Express. When I call this route with curl -I against Express server, it returns:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 24289
ETag: W/"5ee1-y9SVwHfGNt2RUjXNZfi32jVx0EA"
Vary: Accept-Encoding
Date: Tue, 31 Aug 2021 16:05:46 GMT
Connection: keep-alive

I tried to directly do the same thing on fastify. Health-checks would first fail because I was only handling GET, while my server would receive HEAD from the probes.

I, therefore, doubled my handler so now my code has:

  server.get('/*', fp(loader));
  server.head('/*', fp(loader));

The first line handles GET and the second entry gets called for HEAD. It solved the problem locally. When I do $ curl -I http://localhost:3000/categories, it prints:

HTTP/1.1 200 OK
content-type: text/html
vary: accept-encoding
content-length: 24289
Date: Tue, 31 Aug 2021 15:32:51 GMT
Connection: keep-alive

Seems to be working fine. However, when I deploy my thing to the Fargate cluster, the deployment is failing due to health check failing.

service storefront-staging (port 3000) is unhealthy in target-group storefront-stagingTargetGroup due to (reason Health checks failed).

The logs have requests routed to the "healthy" containers. The containers with failing checks only have start and stop operations logged. Don't see any requests being routed to them, including the health checks. I don't understand what is the problem. Please advise.

Starting with fastify version 3.10.x, there is no need to have head handlers, unless those are doing something unusual. Now, fastify can, akin to express handle HEAD by itself based on GET handlers. The default config disables this.


Solution

  • Since Fargate is running code inside containers, for Fastify to work, we have to explicitly pass the bind any. Changed to:

    const address = await server.listen(PORT, '0.0.0.0');
    

    This is working inside a container, as well as locally.