Docs
Concepts
The resource graph
Concepts

The resource graph

Internally, Lithos models your project as a directed acyclic graph of resources. Every individual thing Roblox exposes — an experience, a place, a place's configuration, a developer product, a thumbnail — is one node. Edges encode "this resource needs that resource's outputs to exist before it can be created."

You will rarely inspect the graph directly, but it explains the CLI output.

A resource has four parts

PartDescription
TypeWhat kind of Roblox thing it is (place, developerProduct, thumbnail, …).
IDA stable identifier within your project, e.g. place_start. Lithos generates these from your config.
InputsThe fields you set in lithos.yml plus the outputs of resources it depends on.
OutputsWhat Roblox returned after creating it (asset IDs, version numbers, …). Outputs feed the inputs of dependent resources.

A change is any difference between a resource's persisted inputs and its freshly-computed inputs. That yields create, update, noop, or delete.

How a deploy unfolds

1. Load lithos.yml + state fileread-only2. Live reconciliation passverify experiences, places, products, passesagainst the Roblox API3. Build the desired graph from configread-only4. Diff desired vs. reconciled staterender plan previewread-only5. Confirm (interactive) / auto-approve (CI)then apply in dependency orderapply phase6. Write new statecommit

Steps 1–4 are read-only. Roblox changes start only after confirmation at step 5.

The diagram is simplified. Current deploy also runs preflight, writes a rollback checkpoint before apply, and saves the deployment journal afterward.

Operation kinds

Each node in the diff is exactly one of these:

  • + create — exists in config, not in state.
  • ~ update — exists in both, inputs differ.
  • delete — exists in state, not in config.
  • = noop — inputs match. No API call.
  • skip — its dependencies failed; cannot proceed.

In CI logs you will see lines like:

Succeeded with 0 create(s), 1 update(s), 0 delete(s), 5 noop(s), 0 skip(s)

That summary line is usually the fastest CI signal.

Why deletes are never silent

If you remove a resource from lithos.yml, the next deploy will plan a delete. The YAML is the source of truth.

What is not silent:

  1. The plan preview marks the destructive operation with an explicit warning before any API call.
  2. In an interactive terminal, Lithos prompts for confirmation. Cancel, and nothing happens.
  3. In CI, deletes are still applied, but they are clearly logged.
⚠️

From Roblox's perspective, most deletes are archives. Lithos removes the resource from state and archives the asset where Roblox allows it.

Drift, and what Lithos does about it

If someone changes a Roblox resource through Creator Hub or Studio, the state file no longer matches reality. Lithos calls that drift.

During live reconciliation, Lithos asks Roblox to confirm that each resource it thinks exists actually exists:

  • verified — Roblox confirmed it. Use the persisted state as-is.
  • missing — Roblox said it does not exist. Drop it from state so the next plan re-creates it.
  • skipped — no cheap, authoritative existence check (e.g. thumbnails). Trust the persisted state.
  • unknown — the API call itself failed (network, permission). Trust the persisted state to fail safe.

If a place disappears from the dashboard, the next deploy recreates it instead of trying to update a missing asset. If the API is flaky, Lithos does not destroy state.

Next steps