Open Markdown text in a new tab

Make SoAI faster on low-end servers

Server tuning cuts the work SoAI does on its own host: the background collection, indexing, synchronization, and maintenance that runs whether or not anyone is using the instance. It does not make a model generate faster and it does not raise how many requests the host can carry at once, so use Capacity planning to size the workload and Scheduler and runtime tuning for admission, concurrency, and idle unloading.

Change a server setting

Every control on this page is a Core configuration path, and changing one requires an Administrator with Configuration changes (CONFIG_PATCH).

  1. In the SoAI WebUI, select the Settings button at the right of the header, then Settings.
  2. Select Advanced in the page header.
  3. Paste the full configuration path into Search settings..., change the value, and select Save.
  4. Select Restart SoAI when the WebUI reports a pending restart.

Every setting on this page needs that restart, because SoAI reloads only routing, API rate limiting, and its runtime section in place. Change one group at a time so a saving is attributable and a capability you no longer have is easy to trace back.

Stop unused plugin runtimes

An enabled local plugin can own a backend process and the model runtime inside it, which is usually the largest thing running beside inference. Open Plugins, turn the switch off for a plugin the instance does not serve requests from, and wait for the disable task to finish. Disabling purges that plugin's queued work, stops its active runtime, and moves it to a disabled state that blocks new work until you enable it again. The page requires Plugin read access (PLUGIN_READ) and the switch requires Plugin administration (PLUGIN_ADMIN).

Stop plugin is a different action, since it ends the current runtime and leaves the plugin enabled, so the next request that routes to it starts it again. Use the switch for a backend that should not serve requests at all and Stop plugin when you only want the memory back now. Do not disable a plugin to limit how many backends run at once, because that is MODELS.ROUTING.MAX_CONCURRENT_PLUGINS and belongs in Scheduler and runtime tuning.

The plugin's own state can hold the switch. A quarantined, hardware-incompatible, permanently disabled, or override-pending plugin locks it and relabels it with the state name instead of Enabled, and a plugin with an operation in flight holds it until that operation settles. Install and manage plugins covers those states.

Reduce monitoring collection

Hardware

A sampling thread collects CPU, memory, storage, network, and GPU readings every 3 seconds by default, publishes each snapshot to live consumers, and writes samples to the database while history is on.

  • SYSTEM.HARDWARE.HARDWARE_HISTORY_ENABLED set to false is the first thing to try, because it stops the database writes and the hourly retention pass while the live snapshot and its broadcast continue. Chart then shows History is disabled by the backend.
  • SYSTEM.HARDWARE.MONITORING_INTERVAL_MS raised from 3000 samples less often, so 10000 turns 3 seconds into 10 and cuts the collection work with it.
  • SYSTEM.HARDWARE.DETAILED_GPU_INFO set to false drops the per-GPU running-process query, which is the data behind the Hardware process card, and leaves utilization, memory, drivers, and adapters intact.
  • SYSTEM.HARDWARE.ENABLED set to false stops the sampling thread and the minimum-specs check.

Turning the service off is narrower than it sounds. The Hardware page keeps answering, because its snapshot and capability endpoints query the host on demand rather than reading the sampling thread's output, so live readings survive. What actually stops is the periodic collection behind history and the live displays, along with the hardware_snapshot agent tool, GPU control, and SoAI Bench, which each check the service and refuse while it is off. Disable history instead when the goal is only to stop database growth.

Metrics

Request accounting, stored history, and the live broadcast to the WebUI are three separate workloads, so you can reduce two of them and keep the counts.

  • OBSERVABILITY.METRICS.METRICS_HISTORY.ENABLED set to false stops the periodic history samples, written every 3000 ms by default, and their retention pass. SoAI keeps counting requests and keeps flushing the current aggregate to the database every 30 seconds, so Metrics still works and only the charts and exports lose their history.
  • OBSERVABILITY.METRICS.METRICS_HISTORY.LOGGING_INTERVAL_MS raised keeps history at a coarser granularity.
  • OBSERVABILITY.METRICS.BROADCAST_INTERVAL_MS raised from 1000 publishes live snapshots less often, and Metrics and Dashboard values react more slowly. It saves nothing on an idle server, because the broadcast checks for a subscriber before it builds the snapshot, so no open WebUI already means no work.

Hardware history and metrics history are independent, and disabling one leaves the other running. Monitoring and observability lists the retention settings and the full default set.

Turn off subsystems you do not use

TOOLS.RAG.ENABLED ships on, and while it is on SoAI initializes the RAG service, starts its processing workers, and spawns a Chroma worker process for each storage shard, which is real memory and process overhead on a host that never indexes a document. Set it to false on a server with no Knowledge collections, no document indexing, no RAG retrieval, and no RAG-backed web ingestion. Those capabilities stay unavailable until you enable it again and restart.

TOOLS.MCP.ENABLED is the broader switch, because RAG starts from inside the MCP runtime rather than beside it, so turning MCP off stops the registered tool system and RAG together. Use it only for an inference-only server, since Chat and automations lose every MCP-backed tool with it.

Slow the recurring background tasks

Mail and calendar

Mail synchronization polls every 120 seconds by default and calendar synchronization every 300 seconds, and each pass reads the linked accounts, contacts the remote service for the ones that are due, and updates the cached data. Set INTEGRATIONS.MAIL.SYNC.ENABLED or INTEGRATIONS.CALENDAR.SYNC.ENABLED to false when the server has no linked accounts of that kind, or raise INTEGRATIONS.MAIL.SYNC.INTERVAL_SEC and INTEGRATIONS.CALENDAR.SYNC.INTERVAL_SEC when you want the sync but not that often, accepting that remote changes take longer to appear.

Calendar reminder delivery is separate and unaffected. It runs on its own 60 second task, reads reminders already stored in SoAI, and keeps firing whether or not calendar synchronization is on.

Model discovery

SoAI asks every installed plugin for model metadata on a timer that starts with the server and does not depend on a catalog page being open. Raise MODELS.MANAGER.PERFORMANCE.BACKGROUND_REFRESH_INTERVAL_MS from its default of 60000 when the available models seldom change, and a model added outside SoAI then waits until the next refresh to appear.

Database maintenance and backups

At startup, SoAI checks whether the SQLite database is due for VACUUM maintenance to reclaim unused disk space. The default interval is 720 hours (30 days) since the last successful run, and maintenance is skipped when there is too little space to reclaim. This avoids unnecessary disk work and can add time to startup when maintenance is needed. DATA.DATABASE.SQLITE.VACUUM_INTERVAL_HOURS controls the interval; setting it to 0 disables automatic VACUUM, leaving unused space in the database file available for reuse.

A scheduled backup reads the selected targets, writes an archive, and applies retention, every 24 hours by default. Interval hours sits on the Backup tab, which an Administrator with Backup administration (BACKUP_ADMIN) can open, and DATA.BACKUP.SCHEDULE.INTERVAL_HOURS is the same value in Advanced settings. Setting it to 0 stops the recurring schedule while Create backup stays available and DATA.BACKUP.ENABLED remains true, and SoAI still takes the one backup it requires the first time a target has never completed one.

Keep backups. Change their timing only after measuring backup I/O against the active workload, and read Backup first.

Keep logging useful

Keep OBSERVABILITY.LOGGING.LOG_LEVEL at INFO or a higher severity during normal use. DEBUG and TRACE, the level below DEBUG, add formatting, buffering, and write work at every call site they enable, so use them for a bounded investigation and put the level back afterwards. If nothing consumes the process console output, OBSERVABILITY.LOGGING.CONSOLE_LOGGING set to false removes the duplicate console write while the main log file and the WebUI log stream keep their own handlers.

Application logs are the evidence for diagnosing a backend or plugin failure, so leave the main log on.

Measure the result

  1. Record idle CPU, memory, and disk activity on the host, with the database size, before you change anything.
  2. Apply one change, restart, and let the services settle.
  3. Repeat the same idle window and the same request workload.
  4. Keep the change when the saving is worth the slower updates or the capability you gave up.

Measure from the operating system rather than from SoAI, because several of these settings change the very readings Hardware and Metrics report.

Related documentation