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.
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.