Downcity
PluginsHooks

How to Choose

Use short decision rules to separate action, pipeline, guard, effect, resolve, and service

How to Choose

This page answers one question only:

  • where should this capability actually live

Start with the shortest version

If you want to:

  • explicitly invoke a named capability, use an action
  • progressively transform a value, use pipeline
  • block before the flow continues, use guard
  • keep the main value unchanged and record or sync something, use effect
  • get one final authoritative answer, use resolve
  • own long-lived state, connections, or workers, use a service

Common questions

"I want to add default fields to the input"

Use pipeline.

That is value transformation.

"I want to stop the request immediately if permission is missing"

Use guard.

That is a continuation decision.

"I want to write one audit log every time this happens"

Use effect.

That is a side effect.

"I want to know the user's final role"

Use resolve.

That is a unique-answer problem.

"I want an external caller to trigger a named command"

Use an action.

That is an explicit invocation entry point.

"I want a long-lived cache, connection pool, or background worker"

Use a service.

That is no longer just an extension point.

Common bad splits

using resolve for multi-plugin enrichment

That is usually wrong and should go back to pipeline.

using effect as a hidden reliable job queue

That is usually too heavy and should move into a service or fuller background system.

using guard while also rewriting values

That muddies the semantic role. Put the value rewrite back into pipeline.

One practical decomposition pattern

If one capability needs all of these:

  • an explicit command entry
  • runtime-chain extension
  • long-lived state

then the clean split is often:

  • action for explicit invocation
  • pipeline / guard / effect / resolve for runtime-chain extension
  • service for long-lived state