Filesystem Store Layout

Last modified by Eleni Cojocariu on 2026/10/23 14:40

Reference

This page gives every path the filesystem store writes and what each file in them is called. The Attachment Store explains the store itself, and Locate an Attachment's File on Disk computes a path for a given attachment rather than deriving it by hand.

Every path below is relative to store/file in the permanent directory. They are blob paths, not file paths: on an S3 blob store the same relative paths are the object keys.

How a path is derived

The local/uid serializer writes each name of the reference as its length, a colon, then the name, and leaves the wiki out. Sandbox.WebHome becomes 7:Sandbox7:WebHome. The length is a character count, so a name miscounted by one produces a completely different path.

The hash is then split across three directory levels so that no single directory holds too many entries.

The directory levels

LevelBuilt fromPresent
<wiki>the wiki identifier, xwiki on a single wikialways
<a>/<b>/<rest>the MD5 of the serialized Page reference, split after the first and second charactersalways
locales/<locale>the localeonly for a deleted translation; nothing else writes it
attachments/<a>/<b>/<rest>the MD5 of the attachment name, split the same wayfor an attachment that is still there
deleted-attachments/<a>/<b>/<rest>/<index>the same hash, then the index of the deleted attachmentfor a deleted attachment
deleted-documents/<index>the recycle bin index of the deleted Pagefor a deleted Page

The attachment hash is taken from the plain attachment name, not from a serialized reference.

The files in a directory

FileWhat it is
f<extension>The current content. The name is always f, followed by whatever came after the last . of the attachment name, and by nothing when the name has no dot.
fv<version><extension>One stored version, for instance fv1.2.txt.
<name>.lnkA one-line link holding the path, relative to its own directory, of the blob it stands for. XWiki writes one instead of a second copy whenever the current content is identical to a stored version, which is the usual case, and rewrites it on every new version.
METADATA.xmlThe list of stored versions of the attachment: file name, size, author, version, comment and date for each.
DELETED_ATTACH_METADATA.xmlThe same, for a deleted attachment, written beside METADATA.xml.
content.xmlA deleted Page, serialized whole.
<name>bak, <name>tmpThe backup and temporary files of the two-stage commit. Seeing them on a quiet instance means a write did not finish.

An attachment

XWikiLogo.png, attached to Sandbox.WebHome, ships with the standard flavor and can be checked on any instance:

xwiki/8/3/927acf911df7547cf26345b2c3e89c/          Sandbox.WebHome
  attachments/
    9/2/0bc685fa0da28168319c0126def81b/            XWikiLogo.png
      fv1.1.png                                    version 1.1
      f.png.lnk                                    the current content, holding "fv1.1.png"
      ~METADATA.xml                                the list of stored versions

A deleted attachment

Deleting it moves the whole set one level deeper, under deleted-attachments, keeping the versions and gaining the index the attachment recycle bin gave it. Deleted Attachments and the Recycle Bin covers what becomes of it from there.

xwiki/8/3/927acf911df7547cf26345b2c3e89c/
  deleted-attachments/
    9/2/0bc685fa0da28168319c0126def81b/            the same hash of the attachment name
      1/                                           the index of the deleted attachment
        fv1.1.png
        f.png.lnk
        ~METADATA.xml
        ~DELETED_ATTACH_METADATA.xml

A deleted Page

A deleted Page is a single file, not a directory of files: content.xml is the Page serialized whole, its attachments included, so the attachments directory disappears as the Page is deleted.

xwiki/1/b/017ac37905fda8aca6f74a719cfae4/
  deleted-documents/
    18/                                            the recycle bin index of the Page
      content.xml                                  the Page and its attachments

Deleting one translation rather than the whole Page is the only thing that writes a locales level, and it leaves the Page's attachments where they are:

xwiki/5/3/d3fccc5c1af9cf5ca0170d2e2a2aab/
  attachments/...                                  untouched
  locales/
    fr/
      deleted-documents/
        19/
          content.xml

FAQ

What is the .lnk file for?

It saves a copy. When the current content of an attachment is identical to one of its stored versions, XWiki writes a one-line file pointing at that version rather than storing the same bytes twice.

Can I rename or move these directories?

No. Every path is recomputed from the reference on each read, so a renamed directory is simply a file XWiki can no longer find. Moving the whole store/file tree elsewhere is supported, with store.file.directory; see Sub-Directories in the Permanent Directory.

Why is there no locales directory on my instance?

Because no translation has been deleted. Attaching a file to a translated Page does not create one: attachments belong to the default locale of the Page.

Related

Get Connected