Scheduled Events and Task Queues

SkillProductivity

Lets your agent set up scheduled events and task queues in Mendix apps, including the eight repeat variants and queue throttling.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Scheduled Events and Task Queues skill

About this capability

Scheduled events (Mendix's cron) and task queues in MDL, the eight repeat variants and the fields each takes, and what a queue does and does not throttle. Use when running a microflow on a schedule, or bounding how many background tasks run at once.

What this skill tells your AI

The instructions your AI receives, as published by mendixlabs/mxcli in .claude/skills/mendix/scheduled-events-and-queues/SKILL.md and read by ahel’s review.

When to Use This Skill

Use this skill when the user wants to:

  • Run a microflow on a schedule ("every night at 4", "hourly", "cron", "batch job")
  • Inspect or change an existing scheduled event
  • Limit how many background tasks run at once (a task queue)
  • Run a microflow or Java action call on a queue (IN QUEUE)

These two features are unrelated. A scheduled event does not go through a task queue. Its own concurrency control is OnOverlap.

Scheduled Events

Mendix's cron: run a microflow on a repeating schedule.

-- Inspect
list scheduled events;
list scheduled events in Ops;
describe scheduled event Ops.NightlyCleanup;   -- re-executable MDL

-- Create
create scheduled event Ops.NightlyCleanup (
  Microflow: Ops.SE_Cleanup,
  Repeat: Daily,
  HourOfDay: 4,
  MinuteOfHour: 0,
  TimeZone: Server,
  Enabled: true
);

drop scheduled event Ops.NightlyCleanup;

Microflow and Repeat are always required. show is a synonym for list.

Pick the Repeat first, then use only its fields

Mendix stores the repeat rule as one of eight types, and they differ in which fields they carry — not just in their values. Naming a field from another repeat is an error, not a no-op:

Error: Repeat Daily does not have Multiplier — it takes HourOfDay, MinuteOfHour
RepeatFieldsMeans
MinutelyMultiplierevery N minutes
HourlyMultiplier, MinuteOffsetevery N hours, at :MM past
DailyHourOfDay, MinuteOfHourevery day at HH:MM (no multiplier)
WeeklyWeekdays, HourOfDay, MinuteOfHouron the named days at HH:MM
MonthlyByDateMultiplier, MonthOffset, DayOfMonth, HourOfDay, MinuteOfHourthe Dth of every N months
MonthlyByWeekdayMultiplier, MonthOffset, DaySelector, Weekday, HourOfDay, MinuteOfHourthe last Friday of every N months
YearlyByDateMonth, DayOfMonth, HourOfDay, MinuteOfHourevery 2 January
YearlyByWeekdayMonth, DaySelector, Weekday, HourOfDay, MinuteOfHourthe first Monday of March

Field values:

FieldValue
Multiplier1 or more (defaults to 1)
MinuteOffset0–59
MonthOffset0-based: which month of a multi-month cycle fires
HourOfDay / MinuteOfHour0–23 / 0–59
DayOfMonth / Month1–31 / 1–12
Weekdaysquoted list: 'Monday, Friday' (case-insensitive)
DaySelectorFirst, Second, Third, Fourth, Last
WeekdaySunday … Saturday

Optional on any repeat:

PropertyValuesDefault
Enabledtrue / falsefalse — a new event does not run until you enable it
OnOverlapDelayNext / SkipNextDelayNext
TimeZoneUTC / ServerUTC
StartDateTimeRFC 3339, e.g. '2026-01-01T04:00:00Z'none
Documentationfree textnone

SkipNext drops a run that would overlap the previous one; DelayNext waits.

More examples

-- Every two hours, 23 minutes past
create scheduled event Ops.HourlyPing (
  Microflow: Ops.SE_Ping,
  Repeat: Hourly,
  Multiplier: 2,
  MinuteOffset: 23
);

-- Mondays and Fridays at 09:30
create scheduled event Ops.WeeklyReport (
  Microflow: Ops.SE_Report,
  Repeat: Weekly,
  Weekdays: 'Monday, Friday',
  HourOfDay: 9,
  MinuteOfHour: 30
);

-- The last Friday of every third month, 18:00
create scheduled event Ops.QuarterEnd (
  Microflow: Ops.SE_Close,
  Repeat: MonthlyByWeekday,
  Multiplier: 3,
  MonthOffset: 2,
  DaySelector: Last,
  Weekday: Friday,
  HourOfDay: 18
);

Task Queues

A task queue bounds how many queued calls run at once. Binding a call to it is a separate step — see IN QUEUE.

list queues;
describe queue Ops.OrderProcessing;

create queue Ops.OrderProcessing ( Parallelism: 3, ClusterWide: true );
create queue Ops.Mail;                     -- defaults: parallelism 1, per-instance

create or modify queue Ops.OrderProcessing ( Parallelism: '$MyModule.Workers' );
drop queue Ops.Mail;
PropertyMeaningDefault
Parallelismhow many run at once — an expression, not a number1
ClusterWidetrue = across the cluster, false = per runtime instancefalse

Mendix stores parallelism as an expression string, so 3 and '3' are the same thing and an arbitrary expression is legal.

Common Mistakes

MistakeSymptomFix
Multiplier on a Daily repeatRepeat Daily does not have MultiplierDaily has no multiplier — use HourOfDay/MinuteOfHour, or switch to Hourly
Forgetting Enabled: trueThe event is in the model but never runsSet Enabled: true (the default is false)
TimeZone: serverhas the wrong casing — Mendix stores it as "Server"Use the exact spelling: Server, UTC, DelayNext, SkipNext, Last, Friday
HourOfDay: 24it must be between 0 and 23Hours are 0–23; midnight is 0
Expecting a queue to throttle a scheduled eventNothing changesThey are unrelated — use OnOverlap

Binding a Call to a Queue — IN QUEUE

The queue document only defines the concurrency limit. What actually runs work in the background is the binding on the call activity, and Mendix allows it on exactly two: Call microflow and Call Java action. In MDL that is a trailing in queue clause, in the same position on both — after the argument list, before any on error:

create or modify microflow Ops.ACT_Enqueue ()
begin
  call microflow Ops.ACT_Process(Order = $Order) in queue Ops.OrderProcessing;
  call java action Ops.RefreshData(Url = $Url)   in queue Ops.OrderProcessing;
end;

describe microflow renders the clause back, so the binding round-trips.

Two traps, both verified on mxbuild 11.13.0

A queued Java action must return Nothing. Anything else fails the build with CE7038 "A Java action used for background execution must have a return type of 'Nothing'." mxcli's default return type for create java action is Boolean, so returns void is required, not optional:

create java action Ops.RefreshData(Url: string not null) returns void
as $$ return; $$;

The queue must exist. A missing one is CE1613 "The selected task queue … no longer exists", reported against the call activity — it names the activity, not the script, so a typo is expensive to trace from the build log. mxcli check --references resolves the name first and reports it against the statement instead.

That CE1613 is also the proof the binding is real: drop the queue on a project mxcli wrote and the error appears, naming both the queue and the activity.

A Rewrite Must Restate the Queue

create or replace|modify microflow rebuilds the microflow from the statement, so a binding the script does not restate is gone. mxcli refuses rather than drop it:

Error: microflow Ops.ACT_Caller has 1 call(s) bound to a task queue that this
script does not restate (Ops.MyQueue), and rewriting it would silently drop the
binding.

Add in queue Ops.MyQueue to the call and the rewrite goes through. Without the refusal the binding was written back as null and the project then looked healthier than before — mx check stopped reporting CE1613, because the configuration the error was about had been deleted.

One thing is still refused: a retry policy on a queued call (Queues$QueueFixedRetry / Queues$QueueExponentialRetry). MDL has no syntax for it, so a rewrite cannot preserve it — change that microflow in Studio Pro.

When a Java Action Is the Better Tool

The activity property gives queueing and nothing else. The runtime API, reachable from a Java action, gives queueing and retry, and can queue a Java action directly with no wrapper microflow:

Core.userActionCall("Ops.RefreshData")
    .withParams(url)
    .withExponentialRetry(5, Duration.ofSeconds(2), Duration.ofMinutes(2))
    .executeInBackground(ctx, "Ops.OrderProcessing");

Use Core.microflowCall(...) when the unit of work really is a microflow.

Placing Them in Folders

Both take a folder clause on create, straight after the qualified name:

create scheduled event Ops.SE_Nightly folder 'Private/Scheduled events'
  ( Microflow: Ops.ACT_Nightly, Repeat: Day, StartDateTime: '2026-01-01T02:00:00Z' );

create queue Ops.Q_Imports folder 'Private/Queues' ( Parallelism: 3 );

On create or modify the clause moves an existing document; omitting it leaves placement alone. See organize-project.

Validation Checklist

Before presenting a script:

mxcli check script.mdl                       # catches wrong-repeat fields (MDL-SCHED01)
mxcli check script.mdl -p app.mpr --references
  • Every scheduled event has Microflow and Repeat
  • Only that repeat's fields are used
  • Enabled: true if it is meant to run
  • Enum values spelled exactly (Server, DelayNext, Last, Monday)
  • The target microflow exists and takes no parameters

Querying and Linting

Both document types are in the catalog after refresh catalog:

-- Anything that fires more often than once a minute
select QualifiedName, RepeatDescription, Microflow
from CATALOG.SCHEDULED_EVENTS
where Enabled = 1 and IntervalSeconds < 60;

select QualifiedName, Parallelism, ClusterWide from CATALOG.QUEUES;

A scheduled event counts as a caller of the microflow it runs, so show callers of Ops.SE_Cleanup lists it and the lint rule for orphaned microflows (QUAL004) does not flag it. IntervalSeconds is derived from the schedule, not from the legacy Interval/IntervalType pair Mendix also stores.

Starlark lint rules can iterate both: scheduled_events() yields repeat, interval_seconds, on_overlap, time_zone, enabled, and microflow_name; queues() yields parallelism (a string) and cluster_wide.

Related

  • mxcli syntax scheduled-event, mxcli syntax queue — full syntax reference
  • write-microflows — writing the microflow the event calls
  • project-settings — after-startup / before-shutdown microflows

Scheduled events — Mendix's cron (LIST/DESCRIBE/CREATE [OR MODIFY]/DROP). Repeat: names one of the eight ScheduledEvents$*Schedule variants and only that variant's fields are accepted; a field from another repeat is refused by mxcli check (MDL-SCHED01) and by exec, which call the same function. The document shape is pinned by re-serializing three whole Studio Pro-authored events (Workflow Commons 4.11.0, OIDC SSO 4.6.0, SAML 4.2.1) element by element — modelsdk/gen is wrong about two properties here

the integers are stored as int64 (gen says int32, the #585 mismatch) and StartDateTime is a BSON datetime (gen says string), so both engines share one raw-BSON codec in mdl/scheduledevents. Interval/IntervalType are legacy siblings of Schedule that Studio Pro writes and does not keep in sync — derived on CREATE, carried through untouched on MODIFY. Only the Day and Hour variants have a Studio Pro reference; the other six are metamodel-derived and verified to load. Both are in the catalog (CATALOG.SCHEDULED_EVENTS, CATALOG.QUEUES) and a scheduled event emits a schedule edge into CATALOG.REFS — without it a microflow run only by a scheduled event was reported as dead by show callers, GRAPH_DEAD_ASSETS and lint rule QUAL004.

Task queues (LIST/DESCRIBE/CREATE [OR MODIFY]/DROP QUEUE). Config.ParallelismExpression is a string and the sibling int32 Parallelism is not written — matching all four Studio Pro queues in Business Events 3.12.1. Binding a call to a queue is not yet authorable, so CREATE OR REPLACE|MODIFY MICROFLOW is refused when the stored microflow has a queued call (guard-don't-drop, ADR-0005)

the rebuild used to write QueueSettings back as null, which made mx check go from CE1613 to 0 errors by deleting the user's configuration

Signals

GitHub stars
122
Forks
49
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
scheduled-events-and-queues
Source
github.com/mendixlabs/mxcli