Skip to content

Manage reasoners

Deployed models use reasoners for the computations needed to produce and refresh their outputs. The reasoner type depends on the work the model needs:

Type of reasonerWhat it does
Logic reasonersEvaluate PyRel model logic as part of refreshing model outputs, including the graph algorithms that need it.
Prescriptive reasonersRun prescriptive reasoning workloads, like processing and solving decision problems defined in a PyRel model.
Predictive reasonersRun predictive reasoning workloads, like training and using GNNs through PyRel.

PyRel creates and manages reasoners based on its configuration file and the workloads required by the model. For logic workloads in a deployed model, the refresh process creates the configured reasoner if it does not exist or resumes it if it is suspended. As an admin, you can:

  • View and monitor reasoners and reasoner usage
  • Manage warm (standby) reasoners to reduce startup delays when a deployed model needs a logic reasoner.
  • Scale reasoner capacity to support deployed models’ workloads or reduce costs when workloads are lighter.

Monitor reasoner usage with the app’s observability views. This guide shows you how to check reasoner health, compare trends over time, and build a dashboard in Snowsight, the Snowflake web interface.

To run these monitoring queries, enable app observability and use Snowflake SQL with an active warehouse. The Native App uses Snowflake’s Event Table to report internal metrics about reasoner usage, including memory, CPU, and demand. Once app observability is enabled, the app makes those metrics available in the relationalai.observability_preview schema.

You can check reasoner health by looking at recent memory, CPU, and demand readings. Use the following queries as a starting point, then adjust the time filters and aggregation as needed.

What to doWhen to do it
Check recent memory readingsSee how much memory a reasoner is using compared to its capacity.
Check recent CPU readingsSee how much CPU a reasoner is using compared to its capacity.
Check recent demandCompare demand from model jobs with the reasoner’s capacity.

To see how much of a reasoner’s available memory is currently in use, query the MEMORY_UTILIZATION column from the logic_reasoner__memory_utilization view. MEMORY_UTILIZATION is already reported as a ratio from 0.0 to 1.0, so you do not need a separate memory-capacity column to interpret it.

SELECT
REASONER_NAME,
MEMORY_UTILIZATION,
TIMESTAMP
FROM RELATIONALAI.observability_preview.logic_reasoner__memory_utilization
WHERE TIMESTAMP >= DATEADD(minute, -5, CURRENT_TIMESTAMP())
ORDER BY TIMESTAMP DESC;
  • REASONER_NAME shows which reasoner each reading belongs to.
  • MEMORY_UTILIZATION shows memory use as a fraction of available memory, where 0.50 means about half of the available memory is in use and 1.0 means the reasoner is at its memory limit.
  • TIMESTAMP shows when Snowflake recorded the reading.
  • WHERE TIMESTAMP >= DATEADD(minute, -5, CURRENT_TIMESTAMP()) limits the query to a short recent window so you can check current health without scanning older readings.
  • ORDER BY TIMESTAMP DESC shows the newest readings first.

To see how much of a reasoner’s available CPU is currently in use, query the CPU_UTILIZATION column from the logic_reasoner__cpu_utilization view. CPU_UTILIZATION is already reported as a ratio from 0.0 to 1.0, so you do not need a separate CPU-capacity column to interpret it.

SELECT
REASONER_ID,
REASONER_NAME,
CPU_UTILIZATION,
TIMESTAMP
FROM RELATIONALAI.observability_preview.logic_reasoner__cpu_utilization
WHERE TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP())
ORDER BY TIMESTAMP DESC;
  • REASONER_ID and REASONER_NAME identify which reasoner each reading belongs to.
  • CPU_UTILIZATION shows CPU use as a fraction of available CPU, where 0.50 means about half of the available CPU is in use and 1.0 means the reasoner is at its CPU limit.
  • TIMESTAMP shows when Snowflake recorded the reading.
  • WHERE TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP()) keeps the query focused on recent activity without scanning older readings.
  • ORDER BY TIMESTAMP DESC shows the newest readings first.

To see whether a reasoner is keeping up with recent work, query the DEMAND column from the logic_reasoner__demand view. DEMAND reports job demand as a ratio, and values above 1.0 generally indicate that work is queueing.

SELECT
REASONER_NAME,
DEMAND,
REASONER_CAPACITY,
TIMESTAMP
FROM RELATIONALAI.observability_preview.logic_reasoner__demand
WHERE REASONER_NAME = 'my_reasoner'
AND TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP())
ORDER BY TIMESTAMP DESC;
  • REASONER_NAME identifies which reasoner each reading belongs to.
  • DEMAND shows job demand as a ratio. Values below 1.0 mean the reasoner is handling the current workload without queueing, while values above 1.0 generally indicate queued work.
  • REASONER_CAPACITY shows the capacity tier assigned to the reasoner, such as HIGHMEM_X64_S or HIGHMEM_X64_M, so you can see which tier produced the reading.
  • TIMESTAMP shows when Snowflake recorded the reading.
  • WHERE REASONER_NAME = 'my_reasoner' narrows the query to one reasoner. Replace 'my_reasoner' with the reasoner you want to inspect.
  • AND TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP()) limits the query to recent demand readings.
  • ORDER BY TIMESTAMP DESC shows the newest readings first.

You can compare reasoner trends over time by aggregating memory, CPU, and demand readings into larger time buckets. Use the following queries as a starting point, then adjust the time filters and bucket sizes as needed.

What to doWhen to do it
Compare memory trendsSee whether high memory usage is a one-off spike or a recurring pattern.
Compare CPU trendsSee whether heavy CPU usage is sustained or limited to short bursts.
Compare demand trendsSee whether queued work is isolated to a short window or recurring over time.
Compare multiple metrics togetherSee how memory, CPU, and demand relate to each other during the same time buckets.

To see whether memory pressure is sustained over time, aggregate MEMORY_UTILIZATION readings from the logic_reasoner__memory_utilization view into daily buckets. Looking at both the average and peak values helps you distinguish recurring pressure from isolated spikes.

SELECT
DATE_TRUNC('day', TIMESTAMP) AS day,
REASONER_NAME,
AVG(MEMORY_UTILIZATION) AS avg_memory_utilization,
MAX(MEMORY_UTILIZATION) AS peak_memory_utilization
FROM RELATIONALAI.observability_preview.logic_reasoner__memory_utilization
WHERE TIMESTAMP >= DATEADD(day, -7, CURRENT_TIMESTAMP())
GROUP BY 1, 2
ORDER BY day DESC, REASONER_NAME;
  • DATE_TRUNC('day', TIMESTAMP) AS day groups readings into daily buckets so you can compare one day with another.
  • REASONER_NAME shows which reasoner each aggregated row belongs to.
  • AVG(MEMORY_UTILIZATION) AS avg_memory_utilization shows the average memory use for that day.
  • MAX(MEMORY_UTILIZATION) AS peak_memory_utilization shows the highest memory reading recorded during that day.
  • WHERE TIMESTAMP >= DATEADD(day, -7, CURRENT_TIMESTAMP()) limits the scan to the last 7 days so you can spot recent patterns without pulling older history.

To see whether CPU pressure is sustained over time, aggregate CPU_UTILIZATION readings from the logic_reasoner__cpu_utilization view into hourly buckets. Hourly buckets make it easier to see whether heavy CPU usage is persistent or concentrated in a few short bursts.

SELECT
REASONER_NAME,
DATE_TRUNC('hour', TIMESTAMP) AS hour,
AVG(CPU_UTILIZATION) AS avg_cpu_utilization,
MAX(CPU_UTILIZATION) AS peak_cpu_utilization
FROM RELATIONALAI.observability_preview.logic_reasoner__cpu_utilization
WHERE TIMESTAMP >= DATEADD(hour, -24, CURRENT_TIMESTAMP())
GROUP BY REASONER_NAME, hour
ORDER BY hour DESC, REASONER_NAME;
  • REASONER_NAME shows which reasoner each aggregated row belongs to.
  • DATE_TRUNC('hour', TIMESTAMP) AS hour groups readings into hourly buckets so short-lived spikes do not dominate the view.
  • AVG(CPU_UTILIZATION) AS avg_cpu_utilization shows the average CPU use during each hour.
  • MAX(CPU_UTILIZATION) AS peak_cpu_utilization shows the highest CPU reading recorded during that hour.
  • WHERE TIMESTAMP >= DATEADD(hour, -24, CURRENT_TIMESTAMP()) keeps the query focused on the last 24 hours so you can compare recent busy periods.

To see whether queued work is building over time, aggregate DEMAND readings from the logic_reasoner__demand view into hourly buckets. Keeping REASONER_CAPACITY visible helps you compare observed demand with the capacity tier assigned to each reasoner.

SELECT
REASONER_NAME,
REASONER_CAPACITY,
DATE_TRUNC('hour', TIMESTAMP) AS hour,
AVG(DEMAND) AS avg_demand,
MAX(DEMAND) AS peak_demand
FROM RELATIONALAI.observability_preview.logic_reasoner__demand
WHERE TIMESTAMP >= DATEADD(hour, -24, CURRENT_TIMESTAMP())
GROUP BY REASONER_NAME, REASONER_CAPACITY, hour
ORDER BY hour DESC, REASONER_NAME;
  • REASONER_NAME identifies which reasoner each aggregated row belongs to.
  • REASONER_CAPACITY shows the capacity tier assigned to that reasoner so you can interpret the demand readings in context.
  • DATE_TRUNC('hour', TIMESTAMP) AS hour groups demand readings into hourly buckets so you can see whether queueing is recurring.
  • AVG(DEMAND) AS avg_demand shows the average demand during each hour.
  • MAX(DEMAND) AS peak_demand shows the highest demand reading recorded during that hour.
  • WHERE TIMESTAMP >= DATEADD(hour, -24, CURRENT_TIMESTAMP()) limits the query to the last 24 hours so you can compare recent workload trends.

Use a combined query when you need to compare memory, CPU, and demand in the same recent time buckets. Because joins across preview metric views cost more than single-view queries, keep the input window short.

SELECT
m.REASONER_NAME,
m.REASONER_ID,
TIME_SLICE(m.TIMESTAMP, 10, 'SECOND') AS time_bucket,
AVG(m.MEMORY_UTILIZATION) AS memory_utilization,
AVG(c.CPU_UTILIZATION) AS cpu_utilization,
AVG(d.DEMAND) AS avg_demand
FROM RELATIONALAI.observability_preview.logic_reasoner__memory_utilization AS m
JOIN RELATIONALAI.observability_preview.logic_reasoner__cpu_utilization AS c
ON m.REASONER_ID = c.REASONER_ID
AND TIME_SLICE(m.TIMESTAMP, 10, 'SECOND') = TIME_SLICE(c.TIMESTAMP, 10, 'SECOND')
JOIN RELATIONALAI.observability_preview.logic_reasoner__demand AS d
ON m.REASONER_ID = d.REASONER_ID
AND TIME_SLICE(m.TIMESTAMP, 10, 'SECOND') = TIME_SLICE(d.TIMESTAMP, 10, 'SECOND')
WHERE m.TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP())
AND c.TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP())
AND d.TIMESTAMP >= DATEADD(hour, -1, CURRENT_TIMESTAMP())
GROUP BY 1, 2, 3
ORDER BY time_bucket DESC
LIMIT 10;

The shared TIME_SLICE() bucket is what makes the comparison meaningful. Without it, the three metric streams would rarely line up on exactly the same timestamps.

Start with one bounded query rather than a broad dashboard. That keeps the first dashboard cheap to run and easier to interpret.

  1. Run a bounded monitoring query in Snowsight

    A good starting point is the hourly CPU summary:

    SELECT
    REASONER_NAME,
    DATE_TRUNC('hour', TIMESTAMP) AS hour,
    AVG(CPU_UTILIZATION) AS avg_cpu_utilization,
    MAX(CPU_UTILIZATION) AS peak_cpu_utilization
    FROM RELATIONALAI.observability_preview.logic_reasoner__cpu_utilization
    WHERE TIMESTAMP >= DATEADD(hour, -24, CURRENT_TIMESTAMP())
    GROUP BY REASONER_NAME, hour
    ORDER BY hour DESC, REASONER_NAME;
  2. Create a time-series chart

    After the query finishes, select Chart above the results table. Snowsight generates a chart automatically.

    If it does not choose a line chart:

    • Select the chart-type control and switch it to Line.
    • In the Data section, keep hour as the time column on the x-axis.
    • Use avg_cpu_utilization or peak_cpu_utilization as the y-axis value.
    • If you want one line per reasoner, keep REASONER_NAME in the chart so Snowsight splits the series by reasoner.
  3. Save the chart to a dashboard

    • On the worksheet tab, hover over the worksheet name, select the worksheet More actions menu, then select Move to.
    • To create a new dashboard, select New dashboard, enter a name such as Reasoner monitoring, and then select Create Dashboard.
    • To add the chart to an existing dashboard instead, select that dashboard from the Move to menu. Snowsight moves the worksheet into the dashboard and creates a tile from it.
    • Keep the bounded time filter in the saved query so the tile stays cheap to run.

Use this section when you need to inspect reasoner work for a deployed model or stop work that should no longer continue. It shows how to list jobs, check one job in detail, and cancel a queued or running job with SQL, Python, or the CLI.

For the SQL examples, use a Snowflake session with an active warehouse. Have a reasoner name to list or filter its jobs, or a job ID to inspect or cancel a specific job.

A RelationalAI job is a unit of work that runs on a reasoner. For a deployed model, reasoner jobs perform computations needed to refresh model outputs. Reasoners can also run other work, such as processing changes from data streams.

One reasoner can process more than one job at a time. Each reasoner supports concurrent jobs, and additional work can wait in that reasoner’s queue until capacity is available. That means a reasoner can be available and still feel slow if work is backing up in the queue rather than failing outright.

Concurrent jobs on the same reasoner may impact each other’s performance. Resource-intensive jobs may also increase wait time for other work on the same reasoner.

This guide helps you understand what jobs are running, how long they have been running, and whether any work has been cancelled or failed.

PyRel and the RAI Native App create and submit jobs as work needs to run on a reasoner. As an admin, you use this page to inspect those jobs, check the state of one specific job, or cancel work that should no longer continue.

Use this table to choose the task that matches what you need next:

What to doWhen to do it
View all jobsWhen a reasoner seems slow or blocked and you need to see which jobs are queued, running, or recently finished.
View jobs by statusWhen you need to interpret the current job states and decide whether work is waiting, running, completed, or failing.
Get job detailsWhen you already have a job ID and need to inspect its state, duration, or abort reason more closely.
Cancel a jobWhen a queued or running job should no longer continue on the current reasoner.

Use the following interfaces to view all jobs for a reasoner:

Query the api.jobs view and filter by the REASONER_NAME column. Add REASONER_TYPE if you want to narrow the results to one reasoner type:

-- List jobs for the reasoner named 'my_reasoner'.
SELECT *
FROM relationalai.api.jobs
WHERE REASONER_NAME = 'my_reasoner'
AND REASONER_TYPE = 'logic';
Output
+--------------------------------------+---------------+---------------+---------+----------------------+-------------------------------+-------------------------------+----------+------------------+------------+--------------+
| ID | REASONER_TYPE | REASONER_NAME | STATE | CREATED_BY | CREATED_ON | FINISHED_AT | DURATION | PAYLOAD | TIMEOUT_MS | ABORT_REASON |
|--------------------------------------+---------------+---------------+---------+----------------------+-------------------------------+-------------------------------+----------+------------------+------------+--------------|
| 02c8fa31-1234-5678-90ab-abcdef123456 | logic | my_reasoner | ABORTED | john.doe@company.com | 2024-10-28 08:00:12.123 -0700 | 2024-10-28 08:00:19.766 -0700 | 7643 | {"kind":"query"} | 86400000 | canceled |
+--------------------------------------+---------------+---------------+---------+----------------------+-------------------------------+-------------------------------+----------+------------------+------------+--------------+

Start with ID, STATE, CREATED_ON, FINISHED_AT, and ABORT_REASON. Those fields are usually enough to decide whether you should inspect a job more closely or cancel work that should no longer continue.

Use the STATE column to understand whether work is waiting, running, finished, or needs follow-up:

StateDescription
CREATEDThe job has been accepted by the native app but has not yet been sent to the reasoner queue. If it remains in this state, the reasoner’s resources may be at capacity, or the native app has not yet forwarded the job to the reasoner.
QUEUEDThe job is in the reasoner’s queue, waiting to be processed. If it remains in this state, the reasoner’s concurrency limit has been reached. Wait for the job to leave the queue or cancel it and rerun on a different reasoner.
RUNNINGThe job is currently being processed by the reasoner. A running job may complete normally, be cancelled, or end in an aborted state if an error occurs.
COMPLETEDThe job finished successfully.
CANCELEDThe job was cancelled and reached its final cancelled state.
ABORTEDThe job encountered an error or other issue. Check the ABORT_REASON column for more details.

For API details about the STATE and ABORT_REASON columns, see the api.jobs SQL reference.

Use the following interfaces to inspect one job in detail:

Pass the reasoner type and job ID to api.get_job():

-- Get details for the job with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
CALL relationalai.api.get_job('logic', '02c8fa31-1234-5678-90ab-abcdef123456');
Output
+--------------------------------------+---------------+---------------+-----------+----------------------+-------------------------------+-------------------------------+----------+------------------+------------+--------------+
| ID | REASONER_TYPE | REASONER_NAME | STATE | CREATED_BY | CREATED_ON | FINISHED_AT | DURATION | PAYLOAD | TIMEOUT_MS | ABORT_REASON |
|--------------------------------------+---------------+---------------+-----------+----------------------+-------------------------------+-------------------------------+----------+------------------+------------+--------------|
| 02c8fa31-1234-5678-90ab-abcdef123456 | logic | my_reasoner | COMPLETED | john.doe@company.com | 2024-10-28 08:00:12.123 -0700 | 2024-10-28 08:00:19.766 -0700 | 7643 | {"kind":"query"} | 86400000 | NULL |
+--------------------------------------+---------------+---------------+-----------+----------------------+-------------------------------+-------------------------------+----------+------------------+------------+--------------+

Read the result in this order: STATE, FINISHED_AT, DURATION, then ABORT_REASON. If a job is ABORTED, start with ABORT_REASON, but do not assume it is always the full explanation.

Use the following interfaces to cancel a queued or running job:

Pass the reasoner type and job ID to api.cancel_job():

-- Cancel the job with ID '02c8fa31-1234-5678-90ab-abcdef123456'.
CALL relationalai.api.cancel_job('logic', '02c8fa31-1234-5678-90ab-abcdef123456');
Output
+------------------------+
| Cancelling job |
+------------------------+

It may take a few moments for the job to reach its final cancelled state. Monitor the job again and confirm that STATE is reported as CANCELED.

Logic reasoners evaluate model logic when deployed models refresh their outputs. This guide explains how logic reasoners are created, how to inspect and manage them, and when to step in manually instead of relying on PyRel’s default behavior.

Use a Snowflake session with an active warehouse for the SQL examples. The required application role is shown beside each task: eng_user for inspection and eng_admin for changes.

A deployed model uses a logic reasoner when its refresh plan includes logic workloads. The reasoner evaluates the model’s logic to produce updated outputs. That includes the graph algorithms that use the logic reasoner.

By default, each user gets a dedicated logic reasoner. When a deployed model refreshes its logic outputs, the refresh process resumes the configured logic reasoner if it is suspended or creates one if it does not exist.

Which compute pools host logic reasoners is covered in Configure deployment.

How logic reasoners are created is covered in Configure deployment.

One logic reasoner can process more than one job at a time. Each reasoner supports up to 8 concurrent jobs and a queue capacity of 128 jobs.

Logic reasoners are managed automatically, including creating them when a deployed model’s refresh needs one. Each PyRel user gets a dedicated logic reasoner.

As an admin, you can perform the following actions on logic reasoners:

What to doWhen to do it
View all logic reasonersWhen you want to confirm that a logic reasoner exists and see its high-level state.
Verify that a logic reasoner is readyWhen you want to confirm that one specific logic reasoner is usable with its expected size and settings.
Change a logic reasoner’s auto-suspend settingsWhen you want to trade off lower cost against lower startup latency.
Manually suspend a logic reasonerWhen you want to stop it from consuming compute while it is not needed. Jobs sent to a suspended reasoner fail until the reasoner is resumed again.
Manually resume a suspended logic reasonerWhen you need it available before the next model refresh or when you want to confirm that the reasoner itself can start normally.
Delete a logic reasonerWhen you no longer want to keep that reasoner instance or its current configuration. Deletion is stronger than suspension because it removes the reasoner entirely.

Use the list view when you want to confirm that a logic reasoner exists and see its high-level state.

SELECT *
FROM relationalai.api.reasoners
WHERE TYPE = 'logic';

Start with NAME, SIZE, STATUS, AUTO_SUSPEND_MINS, and SUSPENDS_AT. Those columns usually tell you whether the reasoner is ready to use, scheduled to suspend, or worth inspecting in more detail.

Use the detail view when you want to confirm that one specific logic reasoner is usable with its expected size and settings.

CALL relationalai.api.get_reasoner('logic', 'my_reasoner');

Confirm the following fields first:

  • STATUS = READY
  • SIZE matches the expected instance family
  • AUTO_SUSPEND_MINS matches the current inactivity setting
  • RUNTIME.compute_pool matches the expected logic reasoner pool

If the reasoner exists but is not yet READY, wait for provisioning to complete and run the check again. If it remains unavailable, continue with the troubleshooting section on this page.

Change a logic reasoner’s auto-suspend settings

Section titled “Change a logic reasoner’s auto-suspend settings”

Logic reasoners can be configured to automatically suspend after a period of inactivity, which can help reduce costs when logic workloads are infrequent. By default, newly created logic reasoners suspend after 60 minutes of inactivity unless you set a different value, but you can change this setting based on your workload patterns.

Execute the following to change the auto-suspend timer for a logic reasoner named my_reasoner to 30 minutes:

CALL relationalai.api.alter_reasoner_auto_suspend_mins('logic', 'my_reasoner', 30);

Set the value to 0 to disable auto-suspension.

If you need to suspend a logic reasoner immediately, rather than waiting for the auto-suspend timer, you can do so manually.

Run the following to suspend a logic reasoner named my_reasoner:

CALL relationalai.api.suspend_reasoner('logic', 'my_reasoner');

Use get_reasoner() to check the reasoner’s status and confirm that it has suspended successfully.

Manually resume a suspended logic reasoner

Section titled “Manually resume a suspended logic reasoner”

The model’s refresh process automatically resumes a logic reasoner when it needs to run logic work, but you can also resume it manually if you want it available immediately.

Run the following to resume a logic reasoner named my_reasoner:

CALL relationalai.api.resume_reasoner_async('logic', 'my_reasoner');

It may take a few minutes for the reasoner to start up and become READY again. Use get_reasoner() to check the reasoner’s status and confirm that it has resumed successfully.

Delete a logic reasoner when you no longer want to keep that reasoner instance or its current configuration. Deletion is stronger than suspension because it removes the reasoner entirely.

CALL relationalai.api.delete_reasoner('logic', 'my_reasoner');

When a reasoner is deleted, all current and queued jobs are cancelled. If PyRel is still configured to use that reasoner name, it can recreate the reasoner later when needed.

Troubleshoot common issues with logic reasoners

Section titled “Troubleshoot common issues with logic reasoners”

Use this table to match common logic-reasoner problems to the right next action:

SymptomLikely causeWhat to do next
The expected logic reasoner does not exist.The model has not needed it for a refresh yet, or the configured name does not match the reasoner you expected.Confirm the current reasoners.logic configuration, then check the model’s refresh status.
The reasoner exists but is not READY.Provisioning is still in progress, or startup has stalled.Wait briefly and run get_reasoner() again. If it does not recover, check broader app status.
The reasoner resumes slowly even though nothing is wrong.The reasoner is auto-suspended and needs to start again.Increase AUTO_SUSPEND_MINS or use warm reasoners if startup latency is the main problem.
The reasoner is READY, but model refreshes are still slow.Jobs may be queued or the reasoner may be under sustained load.Use Monitor reasoner usage to inspect demand, CPU, and memory before changing the lifecycle settings.

For adjacent workflows, see Operate RelationalAI and Configure reasoners.

Warm reasoners keep pre-provisioned logic reasoners ready so matching create or resume requests can start faster when warm capacity is available. Use this guide when startup latency is the main problem for logic reasoners and you want faster startup by keeping warm capacity ready, while accepting the additional cost of keeping it active.

Use a Snowflake session with an active warehouse for the SQL examples. The warm-reasoner procedures require the app_admin application role, as noted beside each task.

Warm reasoners are the right setting when startup latency is the main problem for a logic reasoner. If a request needs a logic reasoner size with matching warm capacity available, the app can assign that warm instance instead of provisioning a new reasoner from scratch, so startup can be faster.

Use warm reasoners when all of the following are true:

  • the workload is latency-sensitive at startup
  • the workload uses logic reasoners
  • the problem is startup readiness, not sustained concurrency
  • you accept the additional cost of keeping warm capacity active

Warm reasoners are a preview feature. Only logic reasoners are supported today, so prescriptive workloads, predictive workloads, and CDC are out of scope.

Warm reasoners are also different from a non-suspending reasoner:

  • A non-suspending reasoner keeps the same named reasoner running.
  • A warm reasoner only affects startup. After assignment, the reasoner follows the requested settings, including its normal auto-suspend behavior.

Warm reasoners consume compute while they remain active, even when no request is using them. They improve readiness, but they do not increase the maximum number of same-size reasoners that can run concurrently.

If one warm reasoner is assigned, the app provisions a replacement to keep the configured warm count available. That replacement can still take time to come online, so provisioning can still be slower for later requests in a burst after the existing warm capacity is consumed.

Start with one warm reasoner for the logic size with the worst startup latency. This tells the app to keep matching warm capacity ready for that size:

CALL relationalai.app.enable_warm_reasoner('logic', 'HIGHMEM_X64_S');

The procedure result confirms that the app accepted the warm-reasoner configuration change for that type and size. Treat that result as confirmation of the setting change, not as proof that the warm capacity is already READY.

If one warm reasoner is not enough for a given size, set the exact number of warm reasoners to keep running.

CALL relationalai.app.set_warm_reasoners('logic', 'HIGHMEM_X64_S', 2);

Use this to increase or decrease the warm count for a size. Set the count based on the number of concurrent cold starts you want to absorb, not on the total number of running logic reasoners you need during steady-state work.

The procedure result confirms the new target count. It does not mean that every requested warm reasoner is already READY, because replacement capacity may still be provisioning.

Disable warm reasoners when you want to remove always-on warm capacity and accept slower cold starts in exchange for lower ongoing compute usage.

CALL relationalai.app.disable_warm_reasoner('logic', 'HIGHMEM_X64_S');

You can also set the warm count to 0 with app.set_warm_reasoners(), but disable_warm_reasoner() is the clearest removal workflow.

Once warm reasoners are disabled, the next create or resume for that size may need to wait for normal provisioning again.

Use this page when you need to change the compute pools that host reasoners rather than manage one named reasoner directly. Use it to raise the shared concurrency ceiling for a reasoner size or to reserve always-ready capacity for lower provisioning latency.

Use a Snowflake session with an active warehouse for the SQL examples. Changing shared capacity requires the eng_admin application role, as noted beside the task.

This section is about the app-managed compute pools that host reasoners. It does not resize one named reasoner. Instead, it changes the shared pool limits for a reasoner type and size.

Use compute-pool scaling when you need to change how many same-size reasoners can run at once or how much capacity stays reserved in advance.

SettingWhat it controlsUse it when
MAX_NODESThe maximum number of nodes available for that reasoner type and size. One node corresponds to capacity for one running reasoner.More reasoners of the same size need to run concurrently.
MIN_NODESThe minimum number of nodes that stay reserved and always ready.You want lower provisioning latency for that pool and can accept the extra cost of idle reserved capacity.

Choose this section when the bottleneck is shared capacity for one type and size. If the problem is startup visibility or queueing and you have not confirmed the cause yet, start with Monitor reasoner usage. If you actually need a different size for one named reasoner, recreate that reasoner through the relevant type-specific management workflow instead.

Raise MAX_NODES when the pool needs to support more same-size reasoners at the same time.

CALL relationalai.api.alter_reasoner_pool_node_limits('logic', 'HIGHMEM_X64_S', NULL, 12);

This example raises the concurrency ceiling for HIGHMEM_X64_S logic reasoners to 12 without changing the current MIN_NODES setting.

If starting another reasoner would exceed the pool’s maximum capacity, the request fails instead of waiting for capacity. Use this change when concurrency is the real bottleneck.

  • Raising MAX_NODES does not keep extra capacity warm by itself.
  • If more reasoners actually run after the change, spend can increase.

Reserve capacity for lower provisioning latency

Section titled “Reserve capacity for lower provisioning latency”

Set MIN_NODES when you want some capacity to stay reserved and always ready for a reasoner type and size. This improves readiness for that shared pool, but reserved nodes are billed even when idle.

CALL relationalai.api.alter_reasoner_pool_node_limits('logic', 'HIGHMEM_X64_M', 2, 12);

This example reserves capacity for at least two HIGHMEM_X64_M logic reasoners and allows up to 12 to run concurrently.

Reserved nodes help when normal provisioning latency is the problem for that pool. They do not fix queueing inside one busy reasoner, and they are broader than warm reasoners because they reserve compute-pool capacity rather than pre-provisioning warm logic instances.