Development Choices

Trigger types for a hosted media automation

Author
Joseph Trasatti Member of technical staff
Published
Section
No-Code
Length
6 min read5 sources cited

A hosted media automation starts from one of three trigger forms: a webhook call, a schedule, or an asset upload. Upload triggers fire once per asset and scale with ingest rate, schedules convert an unbounded stream into fixed batches, and webhooks let an external system decide when the work runs.

What a trigger is

A trigger is the event a hosted media automation waits for, and the thing that hands the rest of the flow its input. In MediaFlows a flow can be started by an inbound webhook call, on a schedule, or on asset upload; the trigger is chosen when the flow is built, at the top of the canvas, before any of the blocks beneath it exist (building a flow).

The trigger determines the shape of everything downstream

The three forms differ in more than convenience. Each one sets the flow’s unit of work, its concurrency, and what data is available to the first block.

An upload trigger hands the flow one asset and fires again for the next one, so every block below it is written against a single public ID. A scheduled trigger hands the flow nothing except the fact that the clock advanced, so the first thing it must do is go and find its own work — a search, a list, a query over structured metadata. A webhook trigger hands the flow whatever the caller put in the request body, which means the flow’s input contract is defined outside the media platform entirely.

That is why switching a flow’s trigger after the fact is rarely a one-line change. A flow written to process context.public_id has no meaning under a schedule until something enumerates the assets, and a flow written to iterate a result set does redundant work if it is fired once per upload. Settle the trigger before the blocks.

An upload trigger runs at whatever rate uploads arrive

An upload trigger fires once per asset, on the same upload event Cloudinary can post to a registered notification URL. Its rate is therefore not yours to set — it is the rate your users, your CMS, or your import script are uploading at.

That is fine when uploads arrive one at a time from a form, and it is the trigger most likely to surprise during a bulk import. A migration that pushes 40,000 assets through in an afternoon fires the flow 40,000 times in an afternoon, and every downstream call the flow makes — a transformation, a moderation call, an Admin API read — is multiplied by that number. On the Free plan the Admin API is capped at 500 requests per hour, so a flow that makes two Admin calls per asset stalls at roughly 250 assets an hour regardless of how fast the uploads land (Cloudinary pricing, checked 2026-08-18). Credit consumption moves the same way: one credit covers 1,000 transformations, and transformations are metered over a rolling 30-day window rather than a calendar month, so an import spike does not reset on the 1st — it ages out 30 days after it happened (credits FAQ, checked 2026-08-18).

If the assets are arriving from a spreadsheet-driven bulk load, assume the upload trigger will fire at the full width of that load and size the flow accordingly.

A scheduled trigger converts a stream into a batch

A scheduled trigger fires on a fixed interval and processes whatever it finds. It replaces an unbounded arrival rate with a rate you chose, which is the standard fix once a per-event flow starts colliding with rate limits — the same total work, spread over intervals you control, with a bounded number of items per run instead of a bounded number per second.

The cost is latency and a piece of state. Work now waits up to one interval before anything happens, which rules the pattern out for anything a user is watching. And because the schedule has no event to tell it what is new, the flow needs its own notion of what it has already handled — a tag, a structured-metadata field, a folder move — or every run reprocesses the same assets and pays for them again. Scheduled runs also fail quietly in a way per-event runs do not: nothing external is waiting on the response, so a run that finds nothing because a query broke looks identical to a run that finds nothing because there was nothing to do.

A webhook trigger is the only external decision point

Of the three, only a webhook trigger lets a system outside the media platform decide when work happens. Upload and schedule triggers both fire on conditions the platform observes for itself; a webhook fires because something else made a call.

That makes it the integration point for any step the media platform cannot see the outcome of — most commonly a human approval. A moderation workflow that publishes only after a reviewer clicks approve cannot be expressed as an upload trigger, because upload is not the moment the decision is made. The upload-triggered half stages the asset and notifies the reviewer; the webhook-triggered half runs when the review tool posts the verdict back. The same applies to a CMS publish event, a payment clearing, or a rights check completing in another system.

The trade is that you now own an interface. The caller has to know the URL, authenticate to it, and agree on a payload shape, and that contract has to survive changes to the flow. Whether that interface is better expressed as a flow trigger or as a webhook handler you write yourself is a separate decision from which trigger type fires it.

Triggers are not exclusive

Nothing forces one automation to have one trigger, and mature setups routinely build the same logical automation twice: a per-event version for the live path and a scheduled version that reconciles what the live path missed.

The reason is that per-event triggers drop work. An upload notification is delivered once; if the flow was mid-deploy, a downstream API was returning 500s, or the asset was uploaded through a path that did not fire the event, that asset is simply never processed and nothing reports it. A nightly scheduled flow that searches for assets missing the marker the live flow would have set — a tag, a metadata field, an alt-text value — catches exactly those. Its logic overlaps the live flow almost completely; only the trigger and the initial search differ.

That pairing is worth building deliberately rather than after the first gap is noticed in production. It is also the reason the marker matters more than it looks: it is what makes the two flows agree on what has been done. Prebuilt PowerFlows for moderation, UGC deletion, multilingual alt text and CSV upload ship as starting points and can be duplicated and re-triggered this way (PowerFlows reference). Alt-text generation is a common candidate, since generating alt text on upload leaves a field that is trivially searchable for the reconciling pass.

What to look up next

The things that most often need checking after the trigger is settled: the exact payload each trigger form makes available to the first block, since that determines whether a flow can be re-pointed at a different trigger later; the schedule granularity available on your plan; and how a flow is invoked from outside the canvas, which is covered by the MediaFlows MCP server configuration if the caller is an agent rather than a service.

Sources

  1. building a flow cloudinary.com
  2. notification URL cloudinary.com
  3. Cloudinary pricing cloudinary.com
  4. credits FAQ cloudinary.com
  5. PowerFlows reference cloudinary.com

See also