Voxel Shop beta is live. Expect occasional bugs. Learn more
Modular lag management for every server. Your Server's Performance Guardian!
This release does two things: it makes the automatic optimization actually run, and it adds a diagnostics system that tells you why your server is lagging and where.
The honest framing matters here. Parts of v2.6 shipped configuration that was read, displayed in commands, and then never acted upon. This release closes those gaps and adds verification so they cannot silently reopen.
Lag Diagnostics (new)
The most common admin question is not "what is my TPS" — it is "which build is doing this to me". v2.7 answers that directly.
/lagxpert diagnose scans every loaded chunk and produces a ranked report:
Scoring is relative to limits, not raw counts. A chunk with 40 mobs where the limit is 200 is fine. A chunk with 12 hoppers where the limit is 8 is a problem. Ranking by raw count surfaces the wrong chunks, so every metric contributes its percentage of the limit that actually applies to that world.
Intervention history counts. A chunk LagXpert has had to clean up twenty times in the last hour ranks above one that is merely full right now.
Limits come from the live adaptive engine, so the report reflects what is being enforced at that moment, matching what players experience.
Plain-language conclusions, not just numbers. The report tells you whether load is concentrated in a few chunks or spread everywhere, which violation type dominates, whether memory pressure is the real cause, which world is carrying the load, and — importantly — when the cause is outside LagXpert's scope so you stop looking in the wrong place.
Scanning is two-phase: chunk snapshots are gathered on the owning thread, then all scoring happens asynchronously. Diagnosing lag must not cause lag. Reports are cached for 30 seconds so a command and a GUI opened together share one scan, and concurrent scans are rejected rather than queued.
Diagnostics GUI
/lagxpert diagnose in-game opens an interactive interface with five screens:
Overview — server state, TPS across three windows, memory, entity totals per world, the plain-language diagnosis, and the limits currently in force.
Hotspots — paginated ranked chunk list, colour-coded by severity, each showing which metrics are over limit.
Chunk detail — every measured contributor for one chunk, plus a teleport button to go look at it.
Corrective actions — the audit trail, with timestamps, triggers and counts.
Trends — worst hour of the day, peak players, entity growth direction and 24h projection.
Bedrock compatibility
This was built Bedrock-first rather than retrofitted:
Screen sizes come from BedrockPlayerUtils.getSafeInventorySize, and every slot position is computed from the actual size. Nothing is placed in a slot a Bedrock client will never render.
Materials that Geyser translates badly (spawn eggs, command blocks, structure blocks, knowledge books) are substituted automatically.
Lore is capped at 10 lines, past which Bedrock truncates tooltips unpredictably.
Legacy & colour codes only.
If the inventory cannot be opened at all, the full report is sent as chat text. A Bedrock admin is never left without a diagnosis.
The Bedrock rules now live in one shared helper (BedrockUI) that both the config GUI and the diagnostics GUI route through, so they cannot drift apart. The previous BedrockCompatibleGUI class — 574 lines that registered no listener and had no callers — has been removed rather than left as a maintenance trap.
Emergency Controller
A four-level state machine (NORMAL → WARNING → CRITICAL → EMERGENCY) with hysteresis: 3 consecutive bad readings to escalate, 5 good to de-escalate, minimum 10 seconds per state.
The EMERGENCY tier is now reachable. In the pre-release code computeTargetState() could only ever return NORMAL, WARNING or CRITICAL, which made the entire responses.emergency block — the 25% mob cap, the 16-block AI distance, the 1-minute unload threshold, and the custom command list — permanently dead. It now escalates via dedicated thresholds.tps.emergency / thresholds.ram.emergency values, and also on sustained CRITICAL: a server pinned at 12 TPS for two minutes is an emergency in practice even if it never crosses the raw threshold.
Threshold ordering is validated at startup. Misconfiguring the tiers so one becomes unreachable now logs a warning instead of failing silently.
Responses that now actually execute
Response status
Mob cap multiplier (75% / 50% / 25%)
Status: working
Chunk preloader pause
Status: working
Aggressive chunk unloading
Status: working
AI distance reduction
Status: working
Redstone clock shutdown
Status: working
Block natural spawns
Status: now implemented
Forced item cleanup
Status: now implemented
Server-wide AI freeze
Status: now implemented
Emergency commands
Status: now reachable
The last four were configurable and reported by /lagxpert emergency but had no code acting on them. A new response coordinator consumes them:
Natural spawn blocking filters by SpawnReason. Only environmental pressure is suppressed — spawn eggs, breeding, plugin spawns and commands keep working, because blocking those makes a server look broken rather than busy. The list is operator-configurable, and players with lagxpert.bypass.mobs are exempt.
Forced cleanup runs off-cycle with a CAS latch and a cooldown, so a flapping state cannot stack cleanup sweeps.
AI freeze dispatches per chunk (correct under Folia), skips players and NPC-metadata entities, and on recovery respects your mobs.yml AI rules instead of blanket re-enabling everything. A shutdown mid-emergency lifts the freeze so mobs are never left permanently frozen.
Adaptive Thresholds
Previously this computed multipliers correctly and nothing consumed them — turning the feature on or off only changed numbers in /lagxpert status. It is now the single authority for "what is the limit right now", and is wired into:
StorageListener — hopper, chest, furnace, barrel, dropper, dispenser, shulker, TNT, piston and observer placement limits
EntityListener and SmartMobManager — mob caps
RedstoneCircuitTracker — pulse tolerance and maximum circuit duration
AutoChunkScanTask — so a chunk flagged as overloaded matches what players are actually restricted to
EntityCleanupTask — the per-chunk entity ceiling
Two independent inputs are combined: continuous server health (from TPS and memory) and the discrete emergency state. The more restrictive of the two wins; they are never multiplied, which would compound into unplayable values. Limits are only ever scaled down — your configured value is always the ceiling — and a configurable minimum-multiplier floor prevents collapse. Per-player limits granted through lagxpert.limits.* permissions are honored verbatim and never scaled.
The health factor now takes the worse of the TPS and memory components rather than averaging them, so healthy memory can no longer mask a genuinely bad TPS reading.
Optimization Profiles
profiles.yml previously shipped with zero Java code behind it: no reader, no profile subcommand. /lagxpert profile balanced returned "unknown subcommand".
Now implemented:
Applying a profile writes into the real config files, saves them, and reloads every subsystem. Before the first write the replaced values are snapshotted, so revert restores your configuration rather than an assumed default — and applying a second profile over a first still reverts all the way back. safety.auto-revert-minutes guards against applying an aggressive profile during an incident and forgetting.
Profile keys that do not map to a real setting are reported in the console instead of being silently dropped. The unmappable redstone.disable-clocks key has been replaced with keys that exist.
Other fixes
/lagxpert reload now reloads everything. It previously refreshed only ConfigManager and AbyssManager; a dozen subsystems read their own YAML at construction and kept startup values until a full restart. All are now covered, with per-subsystem failure isolation so one bad section cannot abort the reload.
entity-cleanup.advanced.max-entities-per-chunk is now enforced. It was read into a field and never used. A new pass trims chunks over the ceiling, respecting every existing protection rule (named, tamed, leashed, ridden, persistent, plugin-created, villagers with trades).
MobAIOptimizer honors its own config again. It was reading the emergency controller's getter, which returns a hardcoded 64 when the controller is disabled — so your mobs.yml distance was ignored entirely. The controller may now only tighten the configured radius, never widen it.
plugin.yml corrected. folia-supported: true added (without it Folia refuses to load the plugin regardless of the code). Geyser and Floodgate declared as soft dependencies so Bedrock detection works on first join rather than after a reconnect. The lagxpert.admin.* permission nodes are now declared — previously they were checked but undeclared, so an admin holding only lagxpert.admin saw commands advertised in help and then got "no permission".
Permission checks unified. Help output, tab completion and command execution now consult one method, ending the mismatch between what was advertised and what could be run.
/lagxpert optimize reports honestly. Chunk unloading now runs inline and returns a real count instead of dispatching asynchronously and always reporting zero. Before/after values are coloured by whether they actually improved rather than always green. The hardcoded cache-clear count of 1 is gone, and TPS is labelled as a rolling average instead of showing a meaningless same-tick delta.
/lagxpert status is fully translatable. Its output was hardcoded English; it now uses messages.yml like the rest of the plugin, and additionally shows which emergency responses are in force and which profile is active.
Performance history honors its config. snapshot-interval-seconds and max-history-days were documented but ignored in favour of hardcoded constants. Saved history is also loaded during startup now, rather than reappearing only after the first interval elapsed.
Bedrock player cache no longer leaks. Entries are evicted on disconnect. Detection also identifies Floodgate UUIDs structurally instead of by string prefix, and re-initialises if Geyser or Floodgate finished loading after LagXpert.
LagShield removed. It was a deprecated passthrough with no callers; lagshield.yml was shipped in the JAR but never written or read. Both are gone, along with the legacy message keys.
Configuration
New in emergency-controller.yml:
New in config.yml:
Commands & Permissions
/lagxpert diagnose [chat|refresh]
Permission: lagxpert.admin.diagnostics
Purpose: Find what is causing lag and where
/lagxpert status
Permission: lagxpert.admin.status
Purpose: Live dashboard
/lagxpert optimize
Permission: lagxpert.admin.optimize
Purpose: Full optimization pass
/lagxpert emergency [status|force-normal]
Permission: lagxpert.admin.emergency
Purpose: Emergency state control
/lagxpert profile [list|<name>|revert]
Permission: lagxpert.admin.profile
Purpose: Apply optimization profiles
/lagxpertgui diagnostics
Permission: lagxpert.admin.diagnostics
Purpose: Diagnostics GUI directly
lagxpert.admin implies all of the above. The finer nodes can be granted individually — useful for giving a moderator read-only diagnostics without the ability to rewrite configs or remove entities. Teleporting to a hotspot requires lagxpert.admin.diagnostics.teleport.
Installation
Fresh install
Drop LagXpert-2.7.jar into plugins/.
Start the server to generate configuration files.
Run /lagxpert diagnose to see your server's current state.
Upgrade from v2.6.x
Stop the server.
Replace the old jar with LagXpert-2.7.jar.
Restart to generate emergency-controller.yml and profiles.yml.
Your existing configs remain compatible. New keys use safe defaults.
lagshield.yml is no longer used and can be deleted.
After upgrading, /lagxpert reload applies config edits without a restart — including emergency-controller.yml, which previously required one.
Compatibility
Minecraft: 1.16.x – 1.21.x
Platforms: Spigot, Paper, Purpur, Folia
Java: 11 or higher
Bedrock: Geyser & Floodgate
A note on verification
Because the recurring problem in v2.6 was configuration that looked live but was not, this release was checked against that specific failure mode:
Every previously-dead method was confirmed to have real production call sites.
All 21 shipped YAML files were parsed to confirm they load.
All 21 profile key mappings were confirmed to resolve to real config paths.
The emergency state machine was exercised to confirm all four states are reachable from realistic metrics via both the TPS and memory paths.
All 84 message keys referenced in code were confirmed to exist in messages.yml.
Per-world overrides that were silently ignored
max-entities-per-chunk had no world-aware resolution, so the nether template's 150 was discarded in favour of the global 200.
tnt-per-chunk, pistons-per-chunk, observers-per-chunk had resolvers in WorldConfigManager that nothing ever called: ConfigManager exposed no World-argument delegate for them, and both the placement listener and the chunk scanner used the global value.
All four now resolve per world in the placement listener, the chunk scanner, the entity cleanup pass and the diagnostics engine. All 18 world-aware paths were confirmed to have a valid global fallback, and the shipped nether and end templates each apply 6 active overrides.
The nether template also shipped tnt-per-chunk: 0 commented as "No TNT in nether by default", but 0 means no limit throughout the plugin. Once per-world TNT resolution started working, that would have granted the nether unlimited TNT while claiming the opposite. Corrected to 1 in all three places the template is generated, with the 0 semantics now documented.
Folia correctness of cleanup sweeps
Folia gives each region its own ticking thread, and an entity may only be touched by the thread that owns its chunk. No thread is permitted to sweep an entire world. The cleanup tasks did exactly that, via world.getEntities() and world.getEntitiesByClass().
A new RegionizedSweeper utility enumerates loaded chunks and performs the work on the owning thread. Converted to it:
the item cleaner (scheduled, manual, per-world and emergency-forced)
entity cleanup, including the per-chunk entity ceiling pass
vehicle cleanup
entity counting for performance snapshots and the optimize report
On Spigot and Paper the same dispatch processes chunks in batches across ticks, turning one stalling tick into several short ones — a genuine improvement, since these sweeps run precisely when the server is already struggling. Per-cycle removal budgets are shared across the whole sweep via atomic counters.
Because sweeps now complete asynchronously, /clearitems and /lagxpert optimize report their totals on completion. The optimize phases are chained so each begins only after the previous one finishes, which keeps counts attributable to the right phase and prevents three concurrent sweeps competing for the same budgets.
Verified: no whole-world entity access remains outside comments, and all four entity removal sites sit inside chunk-scoped, sweeper-dispatched methods.
Known limitations
There is no automated test suite. The verification above was performed against the built artifact, not as regression tests.
/lagxpert optimize reports TPS as a rolling average rather than a before/after delta, because the average cannot move within the span of the command.
Players were seeing MemorySection[path='limits.hopper', root='YamlConfiguration'] instead of actual alert messages when placing blocks near or at chunk limits.
What changed:
messages.yml now uses a structured format with full and short sub-keys per message.Action required: Delete your existing plugins/LagXpert/messages.yml and restart the server to regenerate it, or manually update the limits: section to use the new full/short structure.
IllegalArgumentException: Specified map is empty in AsyncChunkAnalyzerServer log was spamming this error when analyzing chunks with no tile entities (empty chunks, deserts, oceans, etc.).
Action required: None. Just update the JAR.
Missing message: lagshield.activated in consoleLagShield was looking for messages at the wrong path in messages.yml.
Action required: None. Just update the JAR.
All block and entity names shown in /chunkstatus, /lagxpert inspect, chunk scan alerts, and near-limit warnings are now fully customizable from messages.yml.
A new translations: section lets you rename items like "Hoppers", "Chests", "Mobs", etc. to match your server's language. The /chunkstatus display is also fully customizable with individual line formats.
Action required: Delete your existing plugins/LagXpert/messages.yml and restart the server to regenerate it with the new translations: and chunkstatus: sections. Then edit the names to your language.
Chests and Trapped Chests were showing as two separate entries in chunk overload alerts, even though they share the same limit. They are now combined into a single "Chests" entry. Same fix applied to Pistons/Sticky Pistons.
The entity cleanup broadcast message (&a, &e, etc.) was not being translated to actual colors, showing raw codes like &e18&a in chat.
LagXpert-2.6.jar with LagXpert-2.6.1.jar.plugins/LagXpert/messages.yml (will regenerate on startup with new translation options).translations: section in messages.yml to your language.This update introduces advanced modules for proactive performance management, including AI optimization, lag shields, and specific controls for vehicles and explosions.
explosions.yml - Prevent massive TNT chain reactions:
settings:
prevent-chain-reaction: true
max-primed-tnt-per-chunk: 20
disable-explosion-drops: false
vehicles.yml - Limit entities per chunk:
limits:
minecarts:
per-chunk: 8
boats:
per-chunk: 5
me.koyere.lagxpert.system.*) with independent configurations.VehicleManager and cleaned up imports in AbilityLimiter.BUILD SUCCESS) and ensured correct registration of listeners and commands.LagXpert-*.jar versions.LagXpert-2.6.jar in your /plugins/ folder.mobs.yml, lagshield.yml, explosions.yml, vehicles.yml, abilities.yml, console-filter.yml./lagxpert reload exists, a full restart is strongly recommended for this update to ensure all new modules initialize correctly.LagXpert v2.5 - World-Aware Enforcement & Activity Tracking
Highlights
⚙️ Technical Improvements
Developer Notes
LagXpert v2.4 - Action Bar Notifications Update
New Features
Action Bar Messages
Enhanced User Experience
⚙️ Configuration Options
New Settings in messages.yml
delivery: restrictions: method: "actionbar" # Options: "chat", "actionbar", "both" cooldown: 5 # Seconds between messagesAvailable Methods:
Message Customization
What This Means for You
For Players
For Server Admins
Bug Fixes
Block Limit Issues Resolved
Affected Blocks
Privacy & Permissions
Alert Privacy System
Custom Limit Permissions
New Permission Examples
lagxpert.alerts.receive - Receive all alertslagxpert.alerts.blocks - Receive block limit alerts onlylagxpert.limits.hoppers.15 - Allow 15 hoppers instead of defaultlagxpert.limits.mobs.50 - Allow 50 mobs instead of default
️ Technical Notes
This update improves the user experience while maintaining all existing functionality. Players will notice cleaner, less intrusive notifications when working with block limits, and limits now work exactly as configured.
broken-block-tracking:
enabled: true
default-grace-period-seconds: 180 # 3 minutes
custom-grace-periods:
DIAMOND_ORE: 300 # 5 minutes for valuable ores
EMERALD_ORE: 300
ANCIENT_DEBRIS: 300
CHEST: 600 # 10 minutes for storage blocks
SPAWNER: 900 # 15 minutes for spawnersalerts:
delivery:
skip-when-no-players-online: true # Reduces alert spamChunkDataCache.getAtomicCounter() - High-performance block countingRecentlyBrokenBlocksTracker - Track recently broken blocks with grace periodsChunkOverloadEvent with better context informationStorageListener for better performance and reliabilityItemCleanerListener for broken block trackingPerformanceTracker with smarter alert logicThanks to the community for reporting these issues and providing valuable feedback that made this update possible.
For detailed configuration and usage instructions, please refer to the main README.md file.
Download: Available on GitHub Releases
Support: Open an issue on GitHub for bug reports or feature requests
License: GPL-3.0
LagXpert v2.3 - Making Minecraft servers faster and more reliable, one optimization at a time.
LagXpert v2.1.1 - Bug Fix Update
Bug Fixes
Technical Details
⚡ What's New
This is a minor maintenance update focused on improving user experience by removing confusing warning messages that appeared on plugin startup. The warnings were harmless but caused unnecessary concern for server administrators.
Compatibility
Download LagXpert v2.1.1 and enjoy a cleaner startup experience!
LagXpert v2.1 - Bug Fixes & Improvements
Critical Bug Fixes
Item Cleaner System:
• Fixed excluded items being deleted despite being in the exclusion list
• Improved item type detection and comparison logic
• Added automatic protection for enchanted items, named items, and items with lore
• Better error handling to prevent crashes with corrupted items
Entity Cleanup System:
• Fixed named entities being removed incorrectly
• Fixed tamed animals being deleted despite protection settings
• Fixed leashed entities being removed when they shouldn't be
• Improved detection of custom names, taming status, and leash connections
• Better respect for all protection configuration options
Configuration System:
• Fixed configuration lists not loading properly from files
• Improved validation to prevent invalid settings
• Added automatic fallback values for missing or empty configurations
• Better error messages when configuration files are missing
Improvements
• Enhanced debug logging for better troubleshooting
• Improved performance with better error handling
• More reliable detection of important entities and items
• Better configuration validation on server startup
⚠️ Important Notes
• Your existing configurations will continue to work
• Excluded items in itemcleaner.yml will now be properly respected
• Protected entities in entitycleanup.yml will now be properly protected
• Enable debug mode in config.yml to see detailed logs if needed
This update focuses on fixing critical issues reported by users. No new features were added to ensure stability.
Release Date: June 2025
Compatibility: Minecraft 1.16.5+ (Spigot/Paper)
LagXpert v2.0 is a complete rewrite that transforms your server's performance management. This isn't just an update - it's a revolution in how you handle server lag.
.jar file in your plugins/ folder/lagxpertgui to configure settings through the GUI.jar file with LagXpert v2.0⚠️ Your server will NOT be affected during the update. All your current limits and settings will continue working.
/lagxpertgui | Open the interactive configuration interface |
/tps | View detailed server performance information |
/tps detailed | Advanced performance statistics |
/tps memory | Memory usage and garbage collection stats |
/tps lagspikes | Recent lag spike analysis |
lagxpert.gui | Access to the configuration GUI |
lagxpert.tps | View server performance information |
lagxpert.monitoring.alerts | Receive performance alerts |
monitoring.yml - TPS and performance tracking settingschunks.yml - Smart chunk management configurationentitycleanup.yml - Advanced entity cleanup optionsconfig/worlds/ - Per-world override configurations/lagxpertgui to familiarize yourself with new features/tps to monitor your server's healthFound a bug? Have a suggestion? Need help?
LagXpert v2.0 sets the foundation for exciting future features:
Thank you for using LagXpert! Your server's performance journey just got a major upgrade. 🎉
We are excited to announce the release of LagXpert v1.3! This update brings a comprehensive overhaul of the plugin, focusing on drastically improved performance, enhanced stability, more intuitive configuration, and new alert control features for a smoother and less intrusive server administration experience.
/chunkstatus and /lagxpert inspect. LagXpert is now lighter than ever!alerts.yml).alerts.yml):alerts.yml file has been redesigned to offer much finer control over which specific types of alerts are active (e.g., limit-reached alerts vs. near-limit warnings, for each block/entity type). This allows server administrators to tailor notifications to their exact needs, complementing the master alert toggle in config.yml./lagxpert inspect <x> <z> [world] Command Now Functional:inspect subcommand has been fully implemented, allowing administrators with the lagxpert.admin permission to get a detailed and efficient breakdown of any loaded chunk's contents by specifying coordinates and an optional world.LagEvent, ChunkOverloadEvent) has been corrected and improved, ensuring proper implementation of Bukkit's HandlerList for better integration with other plugins.config.yml now acts as the central control panel for enabling or disabling main plugin modules (mobs, storage, redstone, alerts, auto-chunk-scan, item-cleaner).mobs.yml, storage.yml, redstone.yml, itemcleaner.yml, task.yml) now focus on the detailed settings for their respective modules.ConfigManager.java for clarity and to prevent loading errors.ItemCleanerTask:ConfigManager, responding correctly to reloads.MessageManager & messages.yml):MessageManager is now correctly initialized by ConfigManager.messages.yml file has been thoroughly reviewed: all missing message keys have been added, discrepancies corrected, and placeholders standardized. All default messages are now in English and fully customizable./lagxpert, /chunkstatus, /clearitems, /abyss) now consistently use MessageManager for all user-facing messages.TabCompleter for /lagxpert and /clearitems, offering more accurate and permission-based suggestions.EntityListener, StorageListener, and RedstoneListener now use optimized counting methods and the new granular alert and cooldown logic.StorageListener has been reviewed for accuracy.RedstoneListener now correctly implements persistent signal control with a delayed task.plugin.yml:lagxpert.bypass.*), covering all limitable elements.permission-message and aliases to command definitions for better Bukkit integration.LagXpertCommand.java.records and "pattern matching for instanceof" where necessary.We hope you enjoy the stability, performance, and customization improvements in LagXpert v1.3. As always, your feedback and bug reports are welcome on our Discord or the plugin page!
LagXpert continues to evolve with new optimizations, enhanced features, and improved user experience. This update focuses on player clarity, admin control, and data persistence.
/chunkstatus OutputNow displays all relevant blocks: hoppers, chests, furnaces, blast furnaces, barrels, shulker boxes, droppers, dispensers, observers, pistons, TNT and more.
Beautifully formatted with clear sections and color coding.
Automatically warns when chunk limits are exceeded.
Items removed via /clearitems or auto-cleanups are now saved per player in plugins/LagXpert/data/abyss/uuid.yml.
Players can safely recover items with /abyss even after a server restart.
/clearitems Subcommands/clearitems all → removes ground items from all enabled worlds.
/clearitems <world> → cleans a specific world by name.
Granular permissions added:
lagxpert.clearitems.all
lagxpert.clearitems.world
Added debug: true in config.yml to output detailed logs in console.
Perfect for diagnostics, testing and reporting issues.
Plugin now tracks:
Number of items removed via cleanup.
Players recovering items via Abyss.
Helps us improve performance and feature planning.
Minecraft 1.16.5 to 1.21.5
Paper, Purpur, Spigot, Pufferfish
Join our support server: Discord: https://discord.gg/xKUjn3EJzR
Please consider leaving a ⭐ review to support continued development!
LagXpert Free - Update 1.1
✅ New Features
⚙ Improvements
Technical Changes
Notes
⭐ Enjoying LagXpert?
If this plugin is helping your server reduce lag and stay clean, please leave a 5-star review — it means a lot and helps the project grow!
Need help or want to suggest a feature?
Join our official support server:
https://discord.gg/xKUjn3EJzR