Performance and scaling
This guide explains how McProgression handles frequent XP actions, what has been optimized for busy servers, and what server owners should configure and monitor. It does not claim a specific player capacity: Minecraft performance depends on the server hardware, worlds, other plugins, and actual action rate. Measure your own workload before setting a capacity target.
What happens when a player earns XP
XP totals and gameplay decisions are updated in memory on the Paper server thread. This keeps level gates and rank changes consistent with the event being processed. McProgression does not need to write a database transaction for every block break. Persistence is delayed and coalesced; SQL I/O runs on a dedicated writer thread. Player-facing actionbar feedback combines rapid awards over its configured window.
The plugin also keeps a compact XP history for staff reports. It aggregates by player, period, action, rank, and LuckPerms group rather than retaining a database event row for each block. This is an audit summary, not a precise block-by-block replay.
Discord is a separate notification path. Individual XP notifications can be high-volume even though the HTTP requests do not block the Paper thread. Prefer useful milestones over a message for every action.
Optimization sequence
The current implementation applies these plugin-side optimizations in order of expected benefit and implementation risk:
- Reduce award hot-path work: reuse the post-award rank score for history and transition handling, cache LuckPerms primary groups with user lifecycle invalidation, and coalesce award-triggered HUD refreshes.
- Bound Discord noise: individual XP posts default to off; optional server-wide summaries group by XP scope and skill; level, rank, and moderator events receive higher queue priority.
- Bound and batch SQL writes: one writer task and one replaceable pending complete snapshot bound backlog; transactional insert, update, and delete operations use JDBC batches.
- Refresh only changed HUDs: a dirty-player queue replaces the full roster rank recalculation every 40 ticks. Preference changes and explicit admin refreshes remain immediate; gameplay refreshes are spread across ticks.
- Limit tablist ranking to online players: the optional board now calculates values only for players whose order can be shown, rather than sorting every stored profile every five seconds. Tablist ordering remains disabled by default.
- Measure before further complexity: incremental rank caches and dirty-key snapshots may save more work, but add invalidation and durability complexity. Use Spark and database timings to establish whether they are worthwhile.
These optimizations do not establish a tested capacity ceiling. The server owner still needs a representative staging run after these changes.
Server owner recommendations
For a busy server, use the following baseline:
- Use SQLite for a single Paper server, or a well-managed MySQL/PostgreSQL service when remote administration is needed. Keep the database close to the Minecraft host. A remote SQL service is not automatically faster than local SQLite. Avoid YAML for large production profiles because it rewrites the full file synchronously.
- Leave the Discord XP-award feed disabled unless staff have a specific need for every award. Keep skill/global rank changes and moderation notifications enabled if those are useful. If XP summaries are enabled, explain to staff that grouped messages summarize a time window and do not provide event-by-event chronology.
- Keep player XP feedback in the default merged actionbar mode. Chat mode sends one message per award and can become noisy during fast actions.
- Do not add a broad block-break cooldown just to reduce database writes. Cooldowns change gameplay and can deny legitimate XP; use them only for a specific repeatable-action or abuse rule.
- Back up the progression database and include a graceful server shutdown in operational procedures. In-memory awards are persisted periodically; sudden process or host loss can lose the most recent save interval.
- Leave tablist ranking off unless you need it. If enabled on a server with many stored profiles, check the staging profiler for its periodic leaderboard refresh cost.
The bossbar no longer does a full-player refresh on a fixed interval. Existing configs may still contain player-display.overlay.refresh-ticks; it is no longer used and can be removed.
Capacity check before launch
Test on a staging server using the same Paper version, plugin set, XP rules, storage backend, and representative world. Generate a realistic burst of the actions that award XP; scale load in steps toward the expected peak rather than jumping directly to it. Track:
- Paper MSPT/tick duration and TPS while the XP workload is active.
- Spark profiler time attributed to McProgression event handlers and rank/history work.
- Database write latency, database errors, and progression save warnings.
- Discord queue-full warnings and dropped-notification counters, if webhook notifications are enabled.
- Player feedback and rank/level changes to confirm that batching has not changed award totals or transition behavior.
Compare the same workload with McProgression disabled to estimate the plugin's incremental cost. Repeat the run long enough to include periodic persistence and history compaction. Test database unavailability and graceful shutdown in staging before relying on remote storage. Do not use a live production world as a synthetic load generator.
Current limits
SQL mode still materializes progression state in memory, and constructing a safe complete snapshot has some server-thread cost. The SQL writer is single-writer and is not a multi-server shared progression service. Discord is best-effort delivery: queue limits and Discord rate limits can delay or drop notifications, and queued messages may not be sent during shutdown. Configure the XP feed as an operational convenience, not as the authoritative XP ledger.
For backend configuration and the single-writer details, see storage.md. For Discord routing and XP summary settings, see discord-webhooks.md.