Skip to content

Catalog vs Application

A flui.yaml declares one of two kinds: Application or CatalogApp. They share the same outer envelope and the same identity model, and both become the same kind of app inside the platform, with the same lifecycle, operations and observability. The only difference is where the container image comes from.

This chapter covers that difference and how the two kinds combine.

kind: Application (your code)

An Application manifest describes an application built from a source repository. You own the code, and the manifest sits in the repository root. At deploy time the platform builds an image from that source, pushes it to a container registry, and deploys the image to the target cluster. The manifest’s build block says what to build (which Dockerfile, which context); the rest of the manifest describes how the resulting image runs.

This is the path for deploying your own service: a web frontend, a backend API, a worker, anything you write and iterate on.

kind: CatalogApp (ready-to-install software)

A CatalogApp manifest describes a pre-packaged application whose image already exists on a container registry. The manifest references the image by registry, name and tag, and adds the installation parameters that make it usable: admin credentials to generate, volume sizes, optional features. There is no build step. Picking a catalog entry produces the same kind of running app as building one from source, without the build pipeline in front of it.

CatalogApp is not limited to entries Flui curates. Any container image, yours or someone else’s, can become a deployable application by wrapping it in a CatalogApp manifest. Declare its registry coordinates, the port it listens on, the healthcheck and the volumes it needs, and you can run it through Flui the same way as the curated entries. The curated catalog and a manifest you write follow the same path; the only difference is who wrote the file.

The same lifecycle on both sides

Once deployed, an application from source and an application from the catalog behave the same inside the platform. The same commands stop, start, restart, scale and delete them. The same dashboard views show their logs, metrics, status and crashes. The same release history records every deploy and rollback. Flui has one toolchain for both, and the dashboard files apps by what they do (Applications, Data, System) rather than by where the image came from.

Three flavours of catalog entry

The catalog has three kinds of entry, by what they are meant to do:

  • Standalone. A complete application that runs on its own and serves its own purpose: an admin tool, a self-hosted service, anything you might install just to use.
  • Building block. An application meant to back other applications rather than be reached directly, most often a database or a message queue. Building blocks are rarely the end goal; your Application is built on top of them.
  • Composed. An entry that bundles several coordinated workloads installed together as one unit: a database, a cache and an app tier, say, provisioned and torn down as one atomic install. Each bundled component is rendered as its own workload, the components come up in dependency order, and the whole stack shows up as a single bundle in its list. A data store it bundles is also listed under Data. See Composed catalog apps for details.

Composing catalog entries

Catalog entries also combine with each other. A standalone catalog entry can declare that it needs a building-block entry (typically a database or a queue) to work, and at install time you pick how the dependency is satisfied:

  • A dedicated instance is provisioned with the consumer, in the same install operation. The building block is created first and the consumer once the building block is healthy, with the credentials the building block generates injected into the consumer’s configuration.
  • An existing instance already deployed on the cluster is reused. The install deploys only the consumer and wires it to the existing building block, whose lifecycle is not part of this operation.

Either way, consumer and building block each get their own entry (the consumer under Applications, the building block under Data), each with its own lifecycle and operations once they are running.

One manifest, more than one install

A manifest is a file. An install is a running thing on a cluster. The difference matters when you want one manifest running twice, such as production and staging from the same repository on the same cluster.

Both installs read the same flui.yaml. They cannot both use the name the file gives, and they cannot both answer on the hostname the file names. So three fields can be overridden when you install:

  • name: what this install is called;
  • exposure: public or internal;
  • domain: the hostname it answers on.

Everything else stays with the manifest: the build, the port, the resources and the configuration defaults. The overrides are the few things that belong to this copy rather than to the code.

The name is part of the identity

On the Application path an app is identified by four things together: the cluster, the repository, the branch and the name. So changing the name does not rename anything. A deploy carrying a name Flui has not seen installs that repository a second time, next to the first.

This part surprises people. Exposure and domain are remembered on the install and keep taking precedence over the manifest on later deploys; otherwise the next deploy from anyone’s machine would quietly move an install back to the manifest’s hostname. The name is not remembered, because it is what the lookup uses to find the install in the first place. Pass it on every deploy that targets that install. If you leave it off once, the next deploy targets a different application.

The catalog side does not have that problem

Installing a catalog entry twice always produces two separate installs, each with its own generated identifier. A second install never lands on top of the first, whatever you call it. Here the name is a label you read in the app list, not a key.

Exposure works differently too: an entry offers the public or internal choice only if it declares that it can run privately. The others run the way their manifest says.

Where each side lives

Where the pieces sit for each kind:

kind: Applicationkind: CatalogApp
ManifestIn the user’s repositoryCurated by the catalog, or user-authored against the spec
ImageBuilt from source by the platform’s build pipeline, pushed to a registryPulled from a registry; no build step
Configurationbuild + the runtime blocksInstallation parameters published by the entry
Install-time overridesName, exposure and domain; the name is part of the app’s identityName and address; exposure only where the entry allows it
Lifecycle operationsThe same on both sides
ObservabilityThe same on both sides

Writing a custom catalog entry

Anything that runs as a container can be a CatalogApp. The requirements are light: the image must be reachable from the cluster, the manifest must declare the port and the healthcheck the runtime uses to know the app is up, and any persistent state the app keeps has to be expressible as a volume. You can write a CatalogApp for any image you want and deploy it through the same path as the curated entries.

The curated catalog is built the same way: each entry is a CatalogApp manifest, written once, reviewed, and made available to everyone.

Where this chapter goes from here