"Is it up?" has two different answers: the process is running, and the app is actually answering requests. Those aren't the same — an app can be "running" while wedged and serving nothing. A /health route answers the second, honest question. This guide builds one (verified on the real runtime) and wires a realistic health story around it, including where Falix genuinely helps and where it honestly doesn't.
| At a glance | |
|---|---|
| You need | A web app on Falix (Node.js or Python) |
| Plan | Any for the route; automatic restarts lean on premium (explained below) |
| Time | Thirty minutes |
Why "the process is alive" isn't enough
The panel marks your server online when it spots the ready line in the console (for Node, a line containing Listening). That's a process signal — it means your code started, not that it's healthy. A server can sit at "online" while its event loop is blocked, its database handle is dead, or every request 500s.
A /health route closes that gap. It's a real HTTP request that only succeeds if your app can actually handle a request right now. That's a stronger promise than "the process didn't exit".
Build a /health route
Keep it cheap and fast — a bare health check just proves the app responds:
const http = require('http');
const PORT = process.env.SERVER_PORT || 8080;
const startedAt = Date.now();
const server = http.createServer((req, res) => {
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status: 'ok', uptime: Math.round((Date.now() - startedAt) / 1000) }));
return;
}
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from Falix!');
});
server.listen(PORT, '0.0.0.0', () => console.log(`Listening on port ${PORT}`));
A request to /health returns 200 with {"status":"ok","uptime":12}. The same idea in Python/Flask (put flask in requirements.txt):
import os, time
from flask import Flask, jsonify
app = Flask(__name__)
started_at = time.time()
@app.route("/health")
def health():
return jsonify(status="ok", uptime=round(time.time() - started_at))
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("SERVER_PORT", 8080)))
Shallow vs deep
The routes above are shallow — "I can answer". If your app is useless without its database, make a deep check that pings the dependency and returns 503 when it's down, so a monitor sees the outage:
if (req.url === '/health') {
try {
await db.query('SELECT 1'); // your real dependency
res.writeHead(200); res.end('{"status":"ok"}');
} catch (e) {
res.writeHead(503); res.end('{"status":"degraded"}');
}
return;
}
Keep it lightweight either way — a monitor hits it every minute, so it shouldn't do heavy work.
Who watches it? The honest part
A route on its own does nothing until something calls it. Here's the truth about what does the calling.
An external uptime monitor (this is the HTTP-probe layer)
The thing that hits your /health on a timer lives outside Falix: an uptime service (UptimeRobot, BetterStack and friends) or your own status page. You give it http://your-address:port/health, it checks every minute, and it alerts you the moment the check fails. This works on any plan, because the monitor is external — Falix just serves the route.
⚠️ Falix does not probe your /health for you. There is no panel feature that calls an HTTP URL on a schedule and restarts on a bad response. Health probing is the external monitor's job. Don't design around a Falix HTTP-probe — it doesn't exist.
What Falix Schedules actually do
Schedules are powerful, but they react to the server's own signals, not to HTTP responses. Here's the real surface:
| Schedules CAN trigger on | Schedules CAN'T do |
|---|---|
| Server started / stopped / crashed | Make an HTTP request to your /health |
| CPU / memory / disk usage crossing a threshold | Read your app's 200/503 reply |
| Server idle, backup completed, player joined/left | Restart based on a route's response |
| Interval / daily / weekly / monthly / manual / git-deploy |
And a schedule's tasks are: command, power action (start/restart/stop/kill), backup, delete files, git sync. So Schedules give you the react-and-restart layer — driven by crashes and resource thresholds — not the probing layer.
The honest health story, in layers
Put the pieces together and stop trying to make one tool do everything:
- The route —
/health, on any plan. The source of truth for "can this app answer?" - The external monitor — hits
/health, pings you when it fails. Any plan (it's an outside service). This is how you find out something's wrong. - Automatic restart — how the server recovers on its own:
- An Event schedule on server crashed → Power action → Start brings a crashed server back up. (The power-action task and running while offline are premium in practice — see Schedules.)
- An Event schedule on a CPU or memory threshold → restart or a warning command, to catch a runaway before it's killed.
- Premium Crash Detection (Settings → Crash Detection tab) bundles auto-restart and health monitoring; the premium Monitoring page adds a health score and crash history. See The Settings page.
🎯 Free-plan reality: On free, power-action tasks and offline schedules are premium, and the session timer stops the server regardless. The dependable free health story is: a
/healthroute + an external monitor that notifies you, then you restart by hand from the Console. Automatic self-healing is where premium earns its keep. See Keeping apps online.
Verify it works
Start the server and request the route from a browser or terminal:
curl http://your-address:port/health
# {"status":"ok","uptime":12}
A 200 with your JSON means the route is live. Point your external monitor at that URL and watch it go green — then stop the server and confirm the monitor notices and alerts you. That alert firing is the whole system working.
Troubleshooting
/healthreturns 200 but the app is still broken — your check is shallow. Make it deep so it actually tests the dependency that's failing.- The monitor can't reach
/health— a port or bind problem: readSERVER_PORTand bind0.0.0.0, and use the exact address from the Network page. See I can't reach my app. - I expected Falix to restart on a bad
/health— it can't; nothing in the panel probes HTTP. Use an external monitor to alert you, and a server crashed or resource threshold schedule (premium power action) to restart. - The server keeps getting killed under load — that's memory, not a health-route issue. See Out of memory.