Why machine doesn't stop when http_checks is defined?

Hi there,

Could you tell me if it’s normal that Fly does not auto-stop machine when I have a http_checks defined to run every 10s?

Here is my configuration:

[[services]]
  protocol = 'tcp'
  internal_port = 8080
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

  [[services.ports]]
    port = 80
    handlers = ['http']
    force_https = true

  [[services.ports]]
    port = 443
    handlers = ['tls', 'http']

  [services.concurrency]
    type = 'requests'
    hard_limit = 100
    soft_limit = 80

  [[services.tcp_checks]]
    interval = '15s'
    timeout = '2s'
    grace_period = '1s'

  [[services.http_checks]]
    interval = '10s'
    timeout = '2s'
    grace_period = '5s'
    method = 'get'
    path = '/resources/healthcheck'
    protocol = 'http'
    tls_skip_verify = false
    [services.http_checks.headers]
      Host = 'dragon-events.fly.dev'

  [[services.http_checks]]
    interval = '30s'
    timeout = '5s'
    grace_period = '10s'
    method = 'GET'
    path = '/litefs/health'

Note that my /resources/healthcheck is doing the following:

// learn more: https://fly.io/docs/reference/configuration/#services-http_checks
import { type LoaderFunctionArgs } from '@remix-run/node';

import { prisma } from '~/app/utils/db.server.ts';

export async function loader({ request }: LoaderFunctionArgs) {
  let host = request.headers.get('X-Forwarded-Host') ?? request.headers.get('host');

  if (host?.endsWith('.localhost:3000')) {
    // for local development
    host = new URL(request.url).hostname;
  }

  const urlToCheck = `${new URL(request.url).protocol}//${host}`;

  try {
    // if we can connect to the database and make a simple query
    // and make a HEAD request to ourselves, then we're good.
    await Promise.all([
      prisma.user.count(),
      fetch(urlToCheck, {
        method: 'HEAD',
        headers: { 'X-Healthcheck': 'true' },
      }).then((r) => {
        if (!r.ok) return Promise.reject(r);
      }),
    ]);
    return new Response('OK');
  } catch (error: unknown) {
    console.log('healthcheck ❌', {
      fetchedUrl: urlToCheck,
      error,
    });
    return new Response('ERROR', { status: 500 });
  }
}

And my application code behind the fetch(urlToFetch, ...) produce a redirect, so the result of this healthcheck is:

2024-08-21T21:06:35.243 app[...] cdg [info] HEAD / 302 - - 16.856 ms
2024-08-21T21:06:35.272 app[...] cdg [info] HEAD /fr 200 - - 22.656 ms

Thanks for your help!

I don’t know, I have a health check and mine goes to sleep after idling. Probably b/c in your health check, you’re going out to the internet and hitting your app externally… which hits the fly proxy, keeping your app up.

Host = 'dragon-events.fly.dev'
fetch(urlToCheck...

Hi @khuezy, thanks for your help understanding the problem!

When I disable the fetch inside my healthcheck, the machine auto-stop as expected.

Thanks again!

1 Like

You probably don’t need to hit your db to make sure your app is healthy. Usually a healthcheck just returns 200 w/ some simple payload, or even 201 w/ no payload.
In your app’s initialization logic (bootstrap), that’s where you’d want to check your db connection.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.