Skip to content

Watch and operate a running application

This page covers what you do after the deploy. It is a loop you will repeat many times: look at the application, decide whether something is wrong, act, and look again. Everything here works the same whether the app came from your own repository or from the catalog.

Is it up, and is it working?

Asking whether an app is OK means asking two separate questions.

Is it up? How many instances should be running, how many are, how much CPU and memory they use, and whether anything has been restarting. This is the platform’s view, and it applies even to an application nobody is visiting.

Is it working? How many requests arrive, how many fail, how slow they are, and what the app says in its logs. This is the user’s view. An app can be up and still completely broken.

Check them in that order. An app that is not up explains every other symptom you will find.

Look at it

Each of these takes the application name or slug, and -c, --cluster to pick the cluster when your profile has more than one. Most take -o json when you want to pipe the output somewhere.

Terminal window
flui app status my-api # is it up
flui app metrics my-api # CPU, memory, network, restarts
flui app traffic my-api # requests, errors, latency
flui app alerts my-api # what has fired, newest first
flui app logs my-api # what the app is saying
flui app crashes my-api # why it fell over

flui app status is the first one to run. It prints the stored facts (status, kind, exposure, when it was last deployed), then the live ones: how many instances are wanted, how many are ready, the image each container runs, and the URL the app answers on, with a warning line if its certificate is not issued yet.

flui app metrics is the current reading: CPU and memory against their reserved amount and their ceiling, network in and out, instances ready and unavailable, and the restart count. A number shown as - means nothing was measured, which is different from zero.

flui app traffic is measured at the edge, in front of the app, so it needs nothing added to your code. Keep three things in mind:

Terminal window
flui app traffic my-api --window 1h
  • The window is an average. On a quiet app a short window reads as zero even when there was traffic, so widen it.
  • If the app has no public route, the command says so instead of printing zeros.
  • If the percentile latencies are flagged as coarse estimates, trust the mean and not the percentiles. The underlying measurement is too coarse for that app.

flui app alerts shows one row per episode, newest first. An alert that keeps firing updates its row instead of adding new ones. --firing narrows it to what is wrong right now, and -n changes how many rows you get. A row marked with * stopped reporting instead of resolving cleanly. Its end time is a guess, so do not read it as the time the app recovered.

Terminal window
flui app alerts my-api --firing

An empty list means nothing was recorded, not that the app is healthy. Pair it with traffic for a live reading.

flui app logs returns the last 100 lines by default. Narrow it down before you read:

Terminal window
flui app logs my-api --level error
flui app logs my-api --tail 500
flui app logs my-api --search "connection refused"

flui app crashes is separate from the log. It is the platform’s own reading of recent failures: a title, a category, the severity, when it was detected, the reason and a suggested action. To open one in full, or mark it handled:

Terminal window
flui app crash my-api <crash-id>
flui app crash my-api <crash-id> --dismiss

When a diagnosis proposes a change, such as a higher memory limit after an out-of-memory kill, Flui does not apply it on its own. flui app crash my-api <crash-id> --apply applies it, and the application restarts.

The levers

There are four, and they do less than people expect: none of them changes what the app is, only how much of it is running.

Terminal window
flui app restart my-api
flui app scale my-api --replicas 3
flui app stop my-api
flui app start my-api

Restart replaces the running instances one at a time, without touching the image or the configuration. Use it to clear a stuck process.

Scale sets the instance count, from 0 to 20.

Stop scales to zero and marks the app stopped. Nothing it holds is deleted, and nothing needs redeploying to bring it back.

Watch out for one thing: stopping writes zero over the instance count. When you start the app again it comes back with a single instance, whatever it ran before. If it was on three, scale it back to three yourself.

Going back to a version that worked

Every deploy and every rollback is recorded as a release. The history is append-only: a rollback adds a new entry marked as a rollback and does not erase the one you are leaving. So you can always tell later what happened, and in what order.

Find the target first, then deploy it.

Terminal window
flui app releases my-api # what has been deployed
flui app releases my-api --current # just the live one
flui app versions my-api # what images exist to go back to

flui app versions lists the images in the registry with their tag, their short digest, how many releases used them, and a marker on the one currently deployed. You pick from that list.

Then put one back:

Terminal window
flui app redeploy my-api a1cac27
flui app redeploy my-api sha256:812bdfd0a833...
flui app redeploy my-api --build <build-id>

redeploy skips the build and puts an existing image back on the cluster. It records a new release like any other deploy.

There is no flui app rollback command. From the terminal, you go back by redeploying a known-good image. The dashboard and the agent surface have a dedicated rollback that picks the target for you; the CLI asks you to name it.

Work that runs on a clock

A scheduled job runs one command on a cron schedule, using the application’s own image and configuration. Your nightly cleanup script sees the same database URL, the same credentials and the same code as the running app, because it is the running app started with a different command. There is nothing separate to build, configure or keep in sync.

A schedule has five parts: a name, a cron expression with the usual five fields, the command, an optional timezone, and what to do when a run is still going when the next one is due.

Overlapping runs are skipped by default. If last night’s job is still running when tonight’s is due, tonight’s run is skipped instead of starting alongside it. That is the safe choice for anything that touches data. You can choose the other behaviours (let runs overlap, or replace the running one) when your job is safe to run twice at once.

Terminal window
flui app schedule create my-api \
--name nightly-cleanup \
--schedule "0 3 * * *" \
--command "node dist/cleanup.js"

The name may contain only lowercase letters, numbers and dashes. The command runs through a shell, so a pipeline or a sequence works as you would write it in a terminal.

FlagEffect
-n, --nameSchedule name. Required.
-s, --scheduleCron expression, five fields. Required.
-x, --commandThe command to run. Required.
-t, --timezoneIANA timezone, e.g. Europe/Rome. Default: cluster time.
--concurrencyAllow, Forbid or Replace. Default: Forbid.
--disabledCreate it suspended, so it does not run yet.

The other schedule commands:

Terminal window
flui app schedule list my-api
flui app schedule runs my-api nightly-cleanup
flui app schedule logs my-api nightly-cleanup
flui app schedule trigger my-api nightly-cleanup
flui app schedule delete my-api nightly-cleanup

runs lists recent runs with their status (succeeded, failed or still running) and whether each was started by the clock or by hand. logs shows the output of the most recent run, or of a specific one with -r, --run. The platform’s retention decides how far back the history goes, and once a run’s instance is gone its logs are gone with it.

trigger starts a run now, independently of the schedule. Use it to test a job without waiting until three in the morning. The run appears in runs marked as manual.

To change a schedule in place, flui app schedule update takes only the flags you pass: --schedule, --command, --timezone, --concurrency. flui app schedule suspend stops it firing without deleting it, and resume turns it back on; a run already in progress finishes.

A schedule declared in the application’s flui.yaml is changed there and released; update and delete refuse it.

flui app manifest is a writing aid

flui app manifest does not print the manifest of a running application. It prints the flui.yaml authoring reference: every field, what it means, and an annotated example you can start a new project from:

Terminal window
flui app manifest
flui app manifest --example
flui app manifest --example nextjs

It runs entirely on your machine, with no cluster, no login and nothing read from the application. It is a writing aid, which is why it is documented with deploying rather than with operating.

Where to go next