A datapack is a folder of JSON files and .mcfunction scripts that the game loads as if it were part of itself. It can change recipes, loot, advancements, world generation and game rules, it runs entirely on the server so nobody has to install anything, and it works the same on vanilla and on Paper. Drop it in world/datapacks/, run /datapack list, and if it is not there, ninety percent of the time the zip has one folder too many inside it. The rest of this post is the other ten percent.
What a datapack can and cannot do#
Datapacks are the game's own modding format, and the list of what they cover has grown a lot. As of the current versions, a pack can define or replace:
- Crafting, smelting, smithing and stonecutting recipes.
- Loot tables, which is how blocks, mobs, chests and fishing decide what to give you.
- Advancements, including hidden ones used purely as event triggers.
- Functions - lists of commands - and the tags that make them run on load or every tick.
- Predicates and item modifiers, the reusable conditions and transformations loot and advancements call.
- Tags: groups of blocks, items, entities, fluids or functions that the game and other packs refer to by name.
- World generation: dimensions, dimension types, biomes, structures, features and noise settings.
- Newer data-driven registries such as damage types, enchantments, banner patterns and trim materials, which vary by version.
What it cannot do is just as important, because people arrive expecting a plugin. A datapack has no way to listen for an arbitrary event; the only hooks are the load and tick function tags and the advancement trigger list. It cannot store state beyond scoreboards and command storage, cannot do anything off the main thread, cannot open a configuration screen, cannot talk to a database, and cannot see or change anything a plugin does. Permissions, chat formatting, land claims, economy and rollbacks are plugin territory.
| Want | Datapack | Plugin |
|---|---|---|
| Change a recipe or a mob drop | Yes, this is what they are for | Overkill |
| Custom dimension or biome | Yes | Rare and difficult |
| React to a block break | Only via advancement triggers | Yes, directly |
| Permissions, economy, claims | No | Yes |
| Works on vanilla and Paper | Yes | Paper or Spigot only |
| Works for Bedrock players via Geyser | Server-side effects, yes | Depends on the plugin |
That last row has a caveat. Because a datapack runs server-side, its effects reach every player, including Bedrock players arriving through Geyser. Anything that depends on a matching resource pack for its appearance will not look right for them, and often not for Java players either unless you also serve the pack. If you are weighing datapacks against plugins in general, Paper, Fabric or vanilla covers which server software gives you which options.
Where datapacks live on a server#
One path: world/datapacks/, where world is whatever level-name says in server.properties. Each pack is either a folder or a .zip, and both behave identically.
world/ level.dat datapacks/ house-rules/ pack.mcmeta data/ vt-multiplayer-sleep.zipTwo things surprise people here.
First, on Paper and Spigot the nether and the end are separate directories - world_nether and world_the_end - but datapacks still only load from the main world's folder. Putting a pack in world_nether/datapacks/ does nothing at all. Packs are loaded once for the server and apply to every dimension.
Second, a zip must have pack.mcmeta at the top level of the archive. If you select a folder in Windows Explorer and compress it, the archive contains one folder which contains pack.mcmeta, and the server ignores it. Select the contents - pack.mcmeta and data - and compress those. The same trap appears in reverse when you use a panel file manager that unpacks archives in place: unpack a correctly built pack zip and you get loose files in datapacks/ rather than a pack folder. Upload the zip and leave it zipped, or unpack it into a folder of its own. SFTP and the file manager has the connection details for whichever route you prefer.
pack.mcmeta, pack_format and the 1.21 rename#
Every pack needs exactly one pack.mcmeta at its root:
{ "pack": { "pack_format": 48, "description": "House rules" }}pack_format is a version number for the data pack format itself, and it changes whenever the game changes the shape of the files. The ones worth memorising:
| Minecraft version | pack_format |
|---|---|
| 1.20 - 1.20.1 | 15 |
| 1.20.2 | 18 |
| 1.20.3 - 1.20.4 | 26 |
| 1.20.5 - 1.20.6 | 41 |
| 1.21 - 1.21.1 | 48 |
Later releases keep incrementing, sometimes twice in a minor version, so take the number for anything newer from that version's release notes rather than guessing. Since 1.20.2 a pack can declare a range instead, which is how a single download supports several versions:
{ "pack": { "pack_format": 48, "supported_formats": { "min_inclusive": 41, "max_inclusive": 57 }, "description": "House rules" }}A wrong pack_format is not always fatal - what actually matters is whether the files inside are in the layout that version expects - but the server flags the pack as incompatible and that is the first thing to check when a pack loads and does nothing.
The layout change that breaks the most old packs came in 1.21: the directories inside data/<namespace>/ went from plural to singular.
| Before 1.21 | From 1.21 |
|---|---|
functions/ | function/ |
advancements/ | advancement/ |
recipes/ | recipe/ |
loot_tables/ | loot_table/ |
predicates/ | predicate/ |
item_modifiers/ | item_modifier/ |
structures/ | structure/ |
tags/functions/ | tags/function/ |
tags/ itself kept its name; the folder inside it did not. A pack written for 1.20 dropped onto a 1.21 server usually loads without error and silently does nothing, because the server looks in function/ and finds an empty registry. If a pack you know is good produces no effect and no log line, check the folder names before anything else.
Namespaces are the other half of the path. data/minecraft/... overrides the game's own files - that is how a pack makes gravel always drop flint, by supplying its own data/minecraft/loot_table/blocks/gravel.json. data/yourname/... defines new things. Namespace and file names must be lowercase, using letters, digits, underscore, dot and hyphen only.
Enabling, ordering and reloading#
Packs found in the folder at world load are enabled automatically the first time; after that, the enabled list and its order live in level.dat. Manage it from the console:
$ datapack list$ datapack list available$ datapack enable "file/house-rules" last$ datapack disable "file/vt-multiplayer-sleep.zip"The name is file/ plus the folder or zip name exactly as it appears on disk, and it needs quoting because of the slash. enable takes an optional position: first, last, before <other> or after <other>.
Order decides who wins. When two packs define the same file - both supply a recipe for the same item, or both replace the same loot table - the later pack in the order replaces the earlier one entirely. It is not a merge. The built-in vanilla pack is always first, which is why any pack at all can override the game. Function tags behave differently and do merge, so two packs that both add to #minecraft:tick both run.
To apply a change without restarting, reload - but be careful which reload you get. On Paper and Spigot, plain /reload is Bukkit's plugin reload, which is a well-known way to break a running server. The vanilla one is namespaced:
$ minecraft:reloadThat rebuilds recipes, loot tables, advancements, tags and functions, and re-runs everything in the #minecraft:load tag. It does not re-generate terrain, and it does not undo anything a function already did.
One more control worth knowing lives in server.properties:
initial-enabled-packs=vanillainitial-disabled-packs=These decide which packs a brand new world starts with, and they are also how you switch on the game's own experimental feature packs on a dedicated server, since there is no world-creation screen to tick a box on. The names of those feature packs change every release, so take them from the release notes. Everything else in that file is covered in server.properties explained.
Vanilla Tweaks and other ready-made packs#
Vanilla Tweaks is the set most servers start with. You pick a game version on the site, tick the packs you want, and download one zip. That outer zip is a container: unzip it and you get one zip per pack, and those inner zips are what goes in datapacks/. Uploading the outer zip is the second most common reason a Vanilla Tweaks install does nothing.
The ones that earn their place on a multiplayer server:
- Graves, which drops a player's inventory into a retrievable grave instead of scattering it. Test it before you rely on it; it interacts badly with
keepInventoryand with any plugin that also handles death. - More mob heads, double shulker shells and fast leaf decay, which are small quality-of-life changes nobody argues about.
- Anti-grief packs for creepers and endermen, which keep the world tidy without a protection plugin.
- Coordinates HUD, which puts coordinates on the scoreboard sidebar for players who cannot see F3.
- Armour statues, the armour stand editor, which is the single most requested building tool.
Some old favourites are now redundant. Multiplayer sleep is a gamerule: playersSleepingPercentage defaults to 100 and setting it to 30 means a third of the players can skip the night. Check whether the game already does the thing before adding a pack that does it.
Vanilla Tweaks also publishes resource packs with the same names, and those are client-side. If you want every player to have them, that is resource-pack and resource-pack-sha1 in server.properties, which is a different job - see MOTD, icon and resource packs. Modrinth carries a large datapack catalogue too. There is no one-click installer for any of this; every pack is a file you upload.
Writing and debugging your own#
The smallest useful pack is four files. A load function to set things up, a tick function guarded by a timer so it is not doing real work twenty times a second, and the two tags that run them.
scoreboard objectives add hr.timer dummytellraw @a {"text":"House rules loaded","color":"gray"}scoreboard players add #t hr.timer 1execute if score #t hr.timer matches 20.. run function houserules:secondscoreboard players set #t hr.timer 0execute as @a[nbt={OnGround:1b}] at @s run particle happy_villager ~ ~ ~{ "values": ["houserules:tick"]}A matching data/minecraft/tags/function/load.json pointing at houserules:load completes it. Run /minecraft:reload and watch the console.
When something does not work, go through this list in order:
- Does
/datapack listshow it as enabled? If it is not even listed, it is the zip structure or the wrong world folder. - Does the console show an error at reload? Parse failures name the file, and usually the line and the character.
- Run the function by hand:
/function houserules:load. If it works manually but not automatically, the tag file is wrong - wrong folder name, wrong namespace, or a typo in the function path. - Check the file extension. Windows hides known extensions by default, so a file you think is
tick.mcfunctionis frequentlytick.mcfunction.txt. - Check your JSON for trailing commas. The game's parser is strict and a trailing comma kills the whole file.
For logic that has to react to something happening, the standard technique is an advancement with a trigger, a reward function and a revoke at the end of that function so it can fire again. It is clumsy compared with a plugin listener, but it covers most of what people want: a player killing a mob, crafting an item, entering a biome or picking something up. The server commands cheatsheet has the selector and execute syntax these functions are built from.
Two limits to know. function-permission-level in server.properties defaults to 2, so functions cannot run commands that need level 3 or 4 such as /ban or /op. And maxCommandChainLength, a gamerule with a default of 65536, caps how many commands one chain may run before the game stops it, which is the safety net that stops a runaway recursive function taking the server with it.
What a bad datapack costs, and how to see it#
Everything a datapack does happens on the main server thread, inside the tick. A function in #minecraft:tick runs twenty times a second forever, and if it opens with execute as @e it walks every loaded entity in every loaded chunk, twenty times a second, whether or not anything changed.
The fixes are the same ones any tick-budget problem has:
- Use a scoreboard counter so the expensive part runs once a second, or once every five, instead of every tick.
- Prefer
@ato@e, and when you need entities, narrow the selector:type=,distance=,tag=,limit=. Atype=filter alone often cuts the work by two orders of magnitude. - Guard with
execute ifbefore doing anything costly, rather than doing the work and discarding it. - Be very careful with
fill,cloneandforceload. A pack that force-loads chunks keeps them ticking forever, which is a permanent cost for a temporary feature.
To measure it, vanilla's own profiler is better than spark here, because it attributes time to individual functions by name:
$ minecraft:debug start$ minecraft:debug stopThat writes a report into the server's debug folder with a per-section breakdown of where tick time went, functions included. spark will tell you that the function manager is expensive; the vanilla report tells you which function. For everything else - plugins, entities, chunk loads, garbage collection - use spark, as described in diagnosing Minecraft lag with spark.
Removing a pack, and surviving a version upgrade#
Disabling a pack that only added recipes, advancements, loot tables or functions is safe. Players keep items they already have, recipes vanish from the book, and nothing in the world is corrupted.
Disabling a pack that added world generation is not safe, and this is the one that loses worlds.
Worldgen packs also have a quieter problem: they only affect chunks generated after they were enabled. Enabling a biome pack on a world people have explored gives you a hard seam between old terrain and new, right at the edge of the generated area. Decide on worldgen before launch, not after - which is one of the reasons to pre-generate inside a border, as in world border and pregeneration.
Version upgrades need a pass over every pack. Check each one has a build for the target version, update pack_format, and rename the directories if you are crossing 1.21. Do it on a copy of the world, not the live one. Minecraft version upgrades covers the wider sequence, and the honest advice is unchanged: take a backup before you enable a pack, not after it breaks something. Game plans on RE:NODE include two backup slots, on demand or on a schedule, and restoring is one button, so there is no excuse for testing a pack on the only copy of your world.
FAQ#
Do players need to install anything to use a datapack?
No. Datapacks are server-side and load before anyone connects. The only exception is appearance: if a pack relies on custom textures or models, those come from a resource pack, which is a separate client-side file.
Why does my pack not appear in /datapack list?
Almost always the archive. pack.mcmeta must sit at the top level of the zip, not inside a wrapper folder. After that, check you put it in the main world folder rather than world_nether, and that level-name in server.properties points where you think it does.
Do datapacks work on Paper?
Fully. Paper loads them exactly as vanilla does. The only Paper-specific trap is /reload, which reloads plugins rather than datapacks; use /minecraft:reload.
Can a datapack replace a plugin?
For recipes, loot, drops, advancement rewards and small rule changes, often yes, and with less overhead. For permissions, economy, land claims, chat formatting or rollback, no - those need an API a datapack does not have.
Will my datapacks still work after a Minecraft update?
Sometimes. Minor updates usually only bump pack_format. The 1.21 rename from plural to singular directory names broke most older packs outright, and new data-driven registries appear regularly. Test every pack on a copy of the world before upgrading the live server.
How many datapacks is too many?
There is no count that is too many. What matters is how much work they do per tick. Twenty packs that only define recipes cost nothing measurable; one pack scanning all entities every tick can cost more than every plugin you have.




Comments
Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.