# Performance Optimization Guide There are several ways to improve the application's performance. The application has been tested on a range of devices, from Raspberry Pi 4 units to NAS and NUC systems. If you are running the application on a lower-end device, fine-tuning the performance settings can significantly improve the user experience. ## Common Causes of Slowness Performance issues are usually caused by: * **Incorrect settings** – The app may restart unexpectedly. Check `app.log` under **Maintenance → Logs** for details. * **Too many background processes** – Disable unnecessary scanners. * **Long scan durations** – Limit the number of scanned devices. * **Excessive disk operations** – Optimize scanning and logging settings. * **Maintenance plugin failures** – If cleanup tasks fail, performance can degrade over time. The application performs regular maintenance and database cleanup. If these tasks are failing, you will see slowdowns. ### Database and Log File Size A large database or oversized log files can impact performance. You can check database and table sizes on the **Maintenance** page. ![DB size check](./img/PERFORMANCE/db_size_check.png) > [!NOTE] > > * For **~100 devices**, the database should be around **50 MB**. > * No table should exceed **10,000 rows** in a healthy system. > * Actual values vary based on network activity and plugin settings. --- ## Maintenance Plugins Two plugins help maintain the system’s performance: ### **1. Database Cleanup (DBCLNP)** * Handles database maintenance and cleanup. * See the [DB Cleanup Plugin Docs](/front/plugins/db_cleanup/README.md). * Ensure it’s not failing by checking logs. * Adjust the schedule (`DBCLNP_RUN_SCHD`) and timeout (`DBCLNP_RUN_TIMEOUT`) if necessary. ### **2. Maintenance (MAINT)** * Cleans logs and performs general maintenance tasks. * See the [Maintenance Plugin Docs](/front/plugins/maintenance/README.md). * Verify proper operation via logs. * Adjust the schedule (`MAINT_RUN_SCHD`) and timeout (`MAINT_RUN_TIMEOUT`) if needed. --- ## Database Performance Tuning The application automatically maintains database performance as data accumulates. However, you can adjust settings to balance CPU usage, disk usage, and responsiveness. ### **WAL Size Tuning (Storage vs. CPU Tradeoff)** The SQLite Write-Ahead Log (WAL) is a temporary file that grows during normal operation. On systems with constrained resources (NAS, Raspberry Pi), controlling WAL size is important. **Setting:** **`PRAGMA_JOURNAL_SIZE_LIMIT`** (default: **50 MB**) | Setting | Effect | Use Case | |---------|--------|----------| | **10–20 MB** | Smaller storage footprint; more frequent disk operations | NAS with SD card (storage priority) | | **50 MB** (default) | Balanced; recommended for most setups | General use | | **75–100 MB** | Smoother performance; larger WAL on disk | High-speed NAS or servers | **Recommendation:** For NAS devices with SD cards, leave at default (50 MB) or increase slightly (75 MB). Avoid very low values (< 10 MB) as they cause frequent disk thrashing and CPU spikes. ### **Automatic Cleanup** The DB cleanup plugin (`DBCLNP`) automatically optimizes query performance and trims old data: - **Deletes old events** – Controlled by `DAYS_TO_KEEP_EVENTS` (default: 90 days) - **Trims plugin history** – Keeps recent entries only (controlled by `PLUGINS_KEEP_HIST`) - **Optimizes queries** – Updates database statistics so queries remain fast **If cleanup fails**, performance degrades quickly. Check **Maintenance → Logs** for errors. If you see frequent failures, increase the timeout (`DBCLNP_RUN_TIMEOUT`). --- ## Scan Frequency and Coverage Frequent scans increase resource usage, network traffic, and database read/write cycles. ### **Optimizations** * **Increase scan intervals** (`_RUN_SCHD`) on busy networks or low-end hardware. * **Increase timeouts** (`_RUN_TIMEOUT`) to avoid plugin failures. * **Reduce subnet size** – e.g., use `/24` instead of `/16` to reduce scan load. * **Enable the deep sleep setting** (`DEEP_SLEEP`) – Lowers CPU usage by extending idle wait times between processing cycles. When enabled, scans may be delayed by up to 1 minute and the UI might become less responsive. Some plugins also include options to limit which devices are scanned. If certain plugins consistently run long, consider narrowing their scope. For example, the **ICMP plugin** allows scanning only IPs that match a specific regular expression. --- ## Plugin Field Authority: `SET_ALWAYS` and `SET_EMPTY` Plugins can be configured to control how aggressively they overwrite existing device field values via two settings: | Setting | Behaviour | |---|---| | `_SET_ALWAYS` | Plugin always overwrites the field, as long as it can resolve a value and the field is not `USER`/`LOCKED` | | `_SET_EMPTY` | Plugin only writes when the field is currently empty | Both settings accept a list of field names (e.g., `devName`, `devFQDN`). See [Name resolution](./NAME_RESOLUTION.md) and [Field locking](./DEVICE_SOURCE_FIELDS.md) docs for details. ### Performance Impact of `SET_ALWAYS` on Name Resolution By default, name resolution (DIGSCAN, NBTSCAN, NSLOOKUP, AVAHISCAN) only runs against **devices that have no name yet**. This keeps DNS query volume proportional to new devices discovered, not the total inventory. When **any** name-resolution plugin has `devName` in its `SET_ALWAYS` list, the system additionally runs a second resolution pass against **all devices whose name is not `USER`/`LOCKED` protected**. This allows a higher-priority plugin (e.g., DIGSCAN) to overwrite names previously set by a lower-priority one (e.g., NBTSCAN). **Cost:** one DNS query per unprotected, already-named device per name-resolution cycle. | Scenario | Devices resolved per cycle | |---|---| | No `SET_ALWAYS` on `devName` | Only new/unknown devices | | `SET_ALWAYS: devName` on any plugin | New/unknown devices **+** all unprotected named devices | > [!WARNING] > On large installations (thousands of devices), enabling `SET_ALWAYS: devName` significantly increases DNS query volume and cycle duration. To mitigate: > > * Increase the scan interval of name-resolution plugins (`DIGSCAN_RUN_SCHD`, `NBTSCAN_RUN_SCHD`, etc.). > * Mark devices whose name should never change as `USER` or `LOCKED` — they are excluded from the re-resolve pass entirely. > * Use `SET_ALWAYS` only on the highest-priority plugin; leave lower-priority plugins without it. The actual number of DB rows updated is logged at `verbose` level under `[Update Device Name] SET_ALWAYS re-resolve - DB rows updated`. --- ## Storing Temporary Files in Memory On devices with slower I/O, you can improve performance by storing temporary files (and optionally the database) in memory using `tmpfs`. > [!WARNING] > Storing the **database** in `tmpfs` is generally discouraged. Use this only if device data and historical records are not required to persist. If needed, you can pair this setup with the `SYNC` plugin to store important persistent data on another node. See the [Plugins docs](./PLUGINS.md) for details. Using `tmpfs` reduces disk writes and speeds up I/O, but **all data stored in memory will be lost on restart**. Below is an optimized `docker-compose.yml` snippet using non-persistent logs, API data, and DB: ```yaml services: netalertx: container_name: netalertx # Use this line for the stable release image: "ghcr.io/netalertx/netalertx:latest" # Or use this line for the latest development build # image: "ghcr.io/netalertx/netalertx-dev:latest" network_mode: "host" restart: unless-stopped cap_drop: # Drop all capabilities for enhanced security - ALL cap_add: # Re-add necessary capabilities - NET_RAW - NET_ADMIN - NET_BIND_SERVICE - CHOWN - SETUID - SETGID volumes: - ${APP_FOLDER}/netalertx/config:/data/config - /etc/localtime:/etc/localtime:ro tmpfs: # All writable runtime state resides under /tmp; comment out to persist logs between restarts - "/tmp:uid=20211,gid=20211,mode=1700,rw,noexec,nosuid,nodev,async,noatime,nodiratime" - "/data/db:uid=20211,gid=20211,mode=1700" # ⚠ You will lose historical data on restart environment: - PORT=${PORT} - APP_CONF_OVERRIDE=${APP_CONF_OVERRIDE} ```