message_retention_policies.html 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. <!DOCTYPE HTML>
  2. <html lang="en" class="sidebar-visible no-js light">
  3. <head>
  4. <!-- Book generated using mdBook -->
  5. <meta charset="UTF-8">
  6. <title>Message Retention Policies - Synapse</title>
  7. <!-- Custom HTML head -->
  8. <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  9. <meta name="description" content="">
  10. <meta name="viewport" content="width=device-width, initial-scale=1">
  11. <meta name="theme-color" content="#ffffff" />
  12. <link rel="icon" href="favicon.svg">
  13. <link rel="shortcut icon" href="favicon.png">
  14. <link rel="stylesheet" href="css/variables.css">
  15. <link rel="stylesheet" href="css/general.css">
  16. <link rel="stylesheet" href="css/chrome.css">
  17. <link rel="stylesheet" href="css/print.css" media="print">
  18. <!-- Fonts -->
  19. <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
  20. <link rel="stylesheet" href="fonts/fonts.css">
  21. <!-- Highlight.js Stylesheets -->
  22. <link rel="stylesheet" href="highlight.css">
  23. <link rel="stylesheet" href="tomorrow-night.css">
  24. <link rel="stylesheet" href="ayu-highlight.css">
  25. <!-- Custom theme stylesheets -->
  26. <link rel="stylesheet" href="docs/website_files/table-of-contents.css">
  27. <link rel="stylesheet" href="docs/website_files/remove-nav-buttons.css">
  28. <link rel="stylesheet" href="docs/website_files/indent-section-headers.css">
  29. <link rel="stylesheet" href="docs/website_files/version-picker.css">
  30. </head>
  31. <body>
  32. <!-- Provide site root to javascript -->
  33. <script type="text/javascript">
  34. var path_to_root = "";
  35. var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
  36. </script>
  37. <!-- Work around some values being stored in localStorage wrapped in quotes -->
  38. <script type="text/javascript">
  39. try {
  40. var theme = localStorage.getItem('mdbook-theme');
  41. var sidebar = localStorage.getItem('mdbook-sidebar');
  42. if (theme.startsWith('"') && theme.endsWith('"')) {
  43. localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
  44. }
  45. if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
  46. localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
  47. }
  48. } catch (e) { }
  49. </script>
  50. <!-- Set the theme before any content is loaded, prevents flash -->
  51. <script type="text/javascript">
  52. var theme;
  53. try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
  54. if (theme === null || theme === undefined) { theme = default_theme; }
  55. var html = document.querySelector('html');
  56. html.classList.remove('no-js')
  57. html.classList.remove('light')
  58. html.classList.add(theme);
  59. html.classList.add('js');
  60. </script>
  61. <!-- Hide / unhide sidebar before it is displayed -->
  62. <script type="text/javascript">
  63. var html = document.querySelector('html');
  64. var sidebar = 'hidden';
  65. if (document.body.clientWidth >= 1080) {
  66. try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
  67. sidebar = sidebar || 'visible';
  68. }
  69. html.classList.remove('sidebar-visible');
  70. html.classList.add("sidebar-" + sidebar);
  71. </script>
  72. <nav id="sidebar" class="sidebar" aria-label="Table of contents">
  73. <div class="sidebar-scrollbox">
  74. <ol class="chapter"><li class="chapter-item expanded affix "><li class="part-title">Introduction</li><li class="chapter-item expanded "><a href="welcome_and_overview.html">Welcome and Overview</a></li><li class="chapter-item expanded affix "><li class="part-title">Setup</li><li class="chapter-item expanded "><a href="setup/installation.html">Installation</a></li><li class="chapter-item expanded "><a href="postgres.html">Using Postgres</a></li><li class="chapter-item expanded "><a href="reverse_proxy.html">Configuring a Reverse Proxy</a></li><li class="chapter-item expanded "><a href="setup/forward_proxy.html">Configuring a Forward/Outbound Proxy</a></li><li class="chapter-item expanded "><a href="turn-howto.html">Configuring a Turn Server</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="setup/turn/coturn.html">coturn TURN server</a></li><li class="chapter-item expanded "><a href="setup/turn/eturnal.html">eturnal TURN server</a></li></ol></li><li class="chapter-item expanded "><a href="delegate.html">Delegation</a></li><li class="chapter-item expanded affix "><li class="part-title">Upgrading</li><li class="chapter-item expanded "><a href="upgrade.html">Upgrading between Synapse Versions</a></li><li class="chapter-item expanded affix "><li class="part-title">Usage</li><li class="chapter-item expanded "><a href="federate.html">Federation</a></li><li class="chapter-item expanded "><a href="usage/configuration/index.html">Configuration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="usage/configuration/config_documentation.html">Configuration Manual</a></li><li class="chapter-item expanded "><a href="usage/configuration/homeserver_sample_config.html">Homeserver Sample Config File</a></li><li class="chapter-item expanded "><a href="usage/configuration/logging_sample_config.html">Logging Sample Config File</a></li><li class="chapter-item expanded "><a href="structured_logging.html">Structured Logging</a></li><li class="chapter-item expanded "><a href="templates.html">Templates</a></li><li class="chapter-item expanded "><a href="usage/configuration/user_authentication/index.html">User Authentication</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="usage/configuration/user_authentication/single_sign_on/index.html">Single-Sign On</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="openid.html">OpenID Connect</a></li><li class="chapter-item expanded "><a href="usage/configuration/user_authentication/single_sign_on/saml.html">SAML</a></li><li class="chapter-item expanded "><a href="usage/configuration/user_authentication/single_sign_on/cas.html">CAS</a></li><li class="chapter-item expanded "><a href="sso_mapping_providers.html">SSO Mapping Providers</a></li></ol></li><li class="chapter-item expanded "><a href="password_auth_providers.html">Password Auth Providers</a></li><li class="chapter-item expanded "><a href="jwt.html">JSON Web Tokens</a></li><li class="chapter-item expanded "><a href="usage/configuration/user_authentication/refresh_tokens.html">Refresh Tokens</a></li></ol></li><li class="chapter-item expanded "><a href="CAPTCHA_SETUP.html">Registration Captcha</a></li><li class="chapter-item expanded "><a href="application_services.html">Application Services</a></li><li class="chapter-item expanded "><a href="server_notices.html">Server Notices</a></li><li class="chapter-item expanded "><a href="consent_tracking.html">Consent Tracking</a></li><li class="chapter-item expanded "><a href="user_directory.html">User Directory</a></li><li class="chapter-item expanded "><a href="message_retention_policies.html" class="active">Message Retention Policies</a></li><li class="chapter-item expanded "><a href="modules/index.html">Pluggable Modules</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="modules/writing_a_module.html">Writing a module</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="modules/spam_checker_callbacks.html">Spam checker callbacks</a></li><li class="chapter-item expanded "><a href="modules/third_party_rules_callbacks.html">Third-party rules callbacks</a></li><li class="chapter-item expanded "><a href="modules/presence_router_callbacks.html">Presence router callbacks</a></li><li class="chapter-item expanded "><a href="modules/account_validity_callbacks.html">Account validity callbacks</a></li><li class="chapter-item expanded "><a href="modules/password_auth_provider_callbacks.html">Password auth provider callbacks</a></li><li class="chapter-item expanded "><a href="modules/background_update_controller_callbacks.html">Background update controller callbacks</a></li><li class="chapter-item expanded "><a href="modules/account_data_callbacks.html">Account data callbacks</a></li><li class="chapter-item expanded "><a href="modules/porting_legacy_module.html">Porting a legacy module to the new interface</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="workers.html">Workers</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="synctl_workers.html">Using synctl with Workers</a></li><li class="chapter-item expanded "><a href="systemd-with-workers/index.html">Systemd</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="usage/administration/index.html">Administration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="usage/administration/admin_api/index.html">Admin API</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="admin_api/account_validity.html">Account Validity</a></li><li class="chapter-item expanded "><a href="usage/administration/admin_api/background_updates.html">Background Updates</a></li><li class="chapter-item expanded "><a href="admin_api/event_reports.html">Event Reports</a></li><li class="chapter-item expanded "><a href="admin_api/media_admin_api.html">Media</a></li><li class="chapter-item expanded "><a href="admin_api/purge_history_api.html">Purge History</a></li><li class="chapter-item expanded "><a href="admin_api/register_api.html">Register Users</a></li><li class="chapter-item expanded "><a href="usage/administration/admin_api/registration_tokens.html">Registration Tokens</a></li><li class="chapter-item expanded "><a href="admin_api/room_membership.html">Manipulate Room Membership</a></li><li class="chapter-item expanded "><a href="admin_api/rooms.html">Rooms</a></li><li class="chapter-item expanded "><a href="admin_api/server_notices.html">Server Notices</a></li><li class="chapter-item expanded "><a href="admin_api/statistics.html">Statistics</a></li><li class="chapter-item expanded "><a href="admin_api/user_admin_api.html">Users</a></li><li class="chapter-item expanded "><a href="admin_api/version_api.html">Server Version</a></li><li class="chapter-item expanded "><a href="usage/administration/admin_api/federation.html">Federation</a></li></ol></li><li class="chapter-item expanded "><a href="manhole.html">Manhole</a></li><li class="chapter-item expanded "><a href="metrics-howto.html">Monitoring</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="usage/administration/monitoring/reporting_homeserver_usage_statistics.html">Reporting Homeserver Usage Statistics</a></li></ol></li><li class="chapter-item expanded "><a href="usage/administration/monthly_active_users.html">Monthly Active Users</a></li><li class="chapter-item expanded "><a href="usage/administration/understanding_synapse_through_grafana_graphs.html">Understanding Synapse Through Grafana Graphs</a></li><li class="chapter-item expanded "><a href="usage/administration/useful_sql_for_admins.html">Useful SQL for Admins</a></li><li class="chapter-item expanded "><a href="usage/administration/database_maintenance_tools.html">Database Maintenance Tools</a></li><li class="chapter-item expanded "><a href="usage/administration/state_groups.html">State Groups</a></li><li class="chapter-item expanded "><a href="usage/administration/request_log.html">Request log format</a></li><li class="chapter-item expanded "><a href="usage/administration/admin_faq.html">Admin FAQ</a></li><li class="chapter-item expanded "><div>Scripts</div></li></ol></li><li class="chapter-item expanded "><li class="part-title">Development</li><li class="chapter-item expanded "><a href="development/contributing_guide.html">Contributing Guide</a></li><li class="chapter-item expanded "><a href="code_style.html">Code Style</a></li><li class="chapter-item expanded "><a href="development/reviews.html">Reviewing Code</a></li><li class="chapter-item expanded "><a href="development/releases.html">Release Cycle</a></li><li class="chapter-item expanded "><a href="development/git.html">Git Usage</a></li><li class="chapter-item expanded "><div>Testing</div></li><li><ol class="section"><li class="chapter-item expanded "><a href="development/demo.html">Demo scripts</a></li></ol></li><li class="chapter-item expanded "><a href="opentracing.html">OpenTracing</a></li><li class="chapter-item expanded "><a href="development/database_schema.html">Database Schemas</a></li><li class="chapter-item expanded "><a href="development/experimental_features.html">Experimental features</a></li><li class="chapter-item expanded "><a href="development/dependencies.html">Dependency management</a></li><li class="chapter-item expanded "><div>Synapse Architecture</div></li><li><ol class="section"><li class="chapter-item expanded "><a href="development/synapse_architecture/cancellation.html">Cancellation</a></li><li class="chapter-item expanded "><a href="log_contexts.html">Log Contexts</a></li><li class="chapter-item expanded "><a href="replication.html">Replication</a></li><li class="chapter-item expanded "><a href="tcp_replication.html">TCP Replication</a></li></ol></li><li class="chapter-item expanded "><a href="development/internal_documentation/index.html">Internal Documentation</a></li><li><ol class="section"><li class="chapter-item expanded "><div>Single Sign-On</div></li><li><ol class="section"><li class="chapter-item expanded "><a href="development/saml.html">SAML</a></li><li class="chapter-item expanded "><a href="development/cas.html">CAS</a></li></ol></li><li class="chapter-item expanded "><a href="development/room-dag-concepts.html">Room DAG concepts</a></li><li class="chapter-item expanded "><div>State Resolution</div></li><li><ol class="section"><li class="chapter-item expanded "><a href="auth_chain_difference_algorithm.html">The Auth Chain Difference Algorithm</a></li></ol></li><li class="chapter-item expanded "><a href="media_repository.html">Media Repository</a></li><li class="chapter-item expanded "><a href="room_and_user_statistics.html">Room and User Statistics</a></li></ol></li><li class="chapter-item expanded "><div>Scripts</div></li><li class="chapter-item expanded affix "><li class="part-title">Other</li><li class="chapter-item expanded "><a href="deprecation_policy.html">Dependency Deprecation Policy</a></li><li class="chapter-item expanded "><a href="other/running_synapse_on_single_board_computers.html">Running Synapse on a Single-Board Computer</a></li></ol>
  75. </div>
  76. <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
  77. </nav>
  78. <div id="page-wrapper" class="page-wrapper">
  79. <div class="page">
  80. <div id="menu-bar-hover-placeholder"></div>
  81. <div id="menu-bar" class="menu-bar sticky bordered">
  82. <div class="left-buttons">
  83. <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
  84. <i class="fa fa-bars"></i>
  85. </button>
  86. <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
  87. <i class="fa fa-paint-brush"></i>
  88. </button>
  89. <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
  90. <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
  91. <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
  92. <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
  93. <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
  94. <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
  95. </ul>
  96. <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
  97. <i class="fa fa-search"></i>
  98. </button>
  99. <div class="version-picker">
  100. <div class="dropdown">
  101. <div class="select">
  102. <span></span>
  103. <i class="fa fa-chevron-down"></i>
  104. </div>
  105. <input type="hidden" name="version">
  106. <ul class="dropdown-menu">
  107. <!-- Versions will be added dynamically in version-picker.js -->
  108. </ul>
  109. </div>
  110. </div>
  111. </div>
  112. <h1 class="menu-title">Synapse</h1>
  113. <div class="right-buttons">
  114. <a href="print.html" title="Print this book" aria-label="Print this book">
  115. <i id="print-button" class="fa fa-print"></i>
  116. </a>
  117. <a href="https://github.com/matrix-org/synapse" title="Git repository" aria-label="Git repository">
  118. <i id="git-repository-button" class="fa fa-github"></i>
  119. </a>
  120. <a href="https://github.com/matrix-org/synapse/edit/develop/docs/message_retention_policies.md" title="Suggest an edit" aria-label="Suggest an edit">
  121. <i id="git-edit-button" class="fa fa-edit"></i>
  122. </a>
  123. </div>
  124. </div>
  125. <div id="search-wrapper" class="hidden">
  126. <form id="searchbar-outer" class="searchbar-outer">
  127. <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
  128. </form>
  129. <div id="searchresults-outer" class="searchresults-outer hidden">
  130. <div id="searchresults-header" class="searchresults-header"></div>
  131. <ul id="searchresults">
  132. </ul>
  133. </div>
  134. </div>
  135. <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
  136. <script type="text/javascript">
  137. document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
  138. document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
  139. Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
  140. link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
  141. });
  142. </script>
  143. <div id="content" class="content">
  144. <main>
  145. <!-- Page table of contents -->
  146. <div class="sidetoc">
  147. <nav class="pagetoc"></nav>
  148. </div>
  149. <h1 id="message-retention-policies"><a class="header" href="#message-retention-policies">Message retention policies</a></h1>
  150. <p>Synapse admins can enable support for message retention policies on
  151. their homeserver. Message retention policies exist at a room level,
  152. follow the semantics described in
  153. <a href="https://github.com/matrix-org/matrix-doc/blob/matthew/msc1763/proposals/1763-configurable-retention-periods.md">MSC1763</a>,
  154. and allow server and room admins to configure how long messages should
  155. be kept in a homeserver's database before being purged from it.
  156. <strong>Please note that, as this feature isn't part of the Matrix
  157. specification yet, this implementation is to be considered as
  158. experimental. There are known bugs which may cause database corruption.
  159. Proceed with caution.</strong> </p>
  160. <p>A message retention policy is mainly defined by its <code>max_lifetime</code>
  161. parameter, which defines how long a message can be kept around after
  162. it was sent to the room. If a room doesn't have a message retention
  163. policy, and there's no default one for a given server, then no message
  164. sent in that room is ever purged on that server.</p>
  165. <p>MSC1763 also specifies semantics for a <code>min_lifetime</code> parameter which
  166. defines the amount of time after which an event <em>can</em> get purged (after
  167. it was sent to the room), but Synapse doesn't currently support it
  168. beyond registering it.</p>
  169. <p>Both <code>max_lifetime</code> and <code>min_lifetime</code> are optional parameters.</p>
  170. <p>Note that message retention policies don't apply to state events.</p>
  171. <p>Once an event reaches its expiry date (defined as the time it was sent
  172. plus the value for <code>max_lifetime</code> in the room), two things happen:</p>
  173. <ul>
  174. <li>Synapse stops serving the event to clients via any endpoint.</li>
  175. <li>The message gets picked up by the next purge job (see the &quot;Purge jobs&quot;
  176. section) and is removed from Synapse's database.</li>
  177. </ul>
  178. <p>Since purge jobs don't run continuously, this means that an event might
  179. stay in a server's database for longer than the value for <code>max_lifetime</code>
  180. in the room would allow, though hidden from clients.</p>
  181. <p>Similarly, if a server (with support for message retention policies
  182. enabled) receives from another server an event that should have been
  183. purged according to its room's policy, then the receiving server will
  184. process and store that event until it's picked up by the next purge job,
  185. though it will always hide it from clients.</p>
  186. <p>Synapse requires at least one message in each room, so it will never
  187. delete the last message in a room. It will, however, hide it from
  188. clients.</p>
  189. <h2 id="server-configuration"><a class="header" href="#server-configuration">Server configuration</a></h2>
  190. <p>Support for this feature can be enabled and configured by adding a the
  191. <code>retention</code> in the Synapse configuration file (see
  192. <a href="usage/configuration/config_documentation.html#retention">configuration manual</a>).</p>
  193. <p>To enable support for message retention policies, set the setting
  194. <code>enabled</code> in this section to <code>true</code>.</p>
  195. <h3 id="default-policy"><a class="header" href="#default-policy">Default policy</a></h3>
  196. <p>A default message retention policy is a policy defined in Synapse's
  197. configuration that is used by Synapse for every room that doesn't have a
  198. message retention policy configured in its state. This allows server
  199. admins to ensure that messages are never kept indefinitely in a server's
  200. database. </p>
  201. <p>A default policy can be defined as such, by adding the <code>retention</code> option in
  202. the configuration file and adding these sub-options:</p>
  203. <pre><code class="language-yaml">default_policy:
  204. min_lifetime: 1d
  205. max_lifetime: 1y
  206. </code></pre>
  207. <p>Here, <code>min_lifetime</code> and <code>max_lifetime</code> have the same meaning and level
  208. of support as previously described. They can be expressed either as a
  209. duration (using the units <code>s</code> (seconds), <code>m</code> (minutes), <code>h</code> (hours),
  210. <code>d</code> (days), <code>w</code> (weeks) and <code>y</code> (years)) or as a number of milliseconds.</p>
  211. <h3 id="purge-jobs"><a class="header" href="#purge-jobs">Purge jobs</a></h3>
  212. <p>Purge jobs are the jobs that Synapse runs in the background to purge
  213. expired events from the database. They are only run if support for
  214. message retention policies is enabled in the server's configuration. If
  215. no configuration for purge jobs is configured by the server admin,
  216. Synapse will use a default configuration, which is described here in the
  217. <a href="usage/configuration/config_documentation.html#retention">configuration manual</a>.</p>
  218. <p>Some server admins might want a finer control on when events are removed
  219. depending on an event's room's policy. This can be done by setting the
  220. <code>purge_jobs</code> sub-section in the <code>retention</code> section of the configuration
  221. file. An example of such configuration could be:</p>
  222. <pre><code class="language-yaml">purge_jobs:
  223. - longest_max_lifetime: 3d
  224. interval: 12h
  225. - shortest_max_lifetime: 3d
  226. longest_max_lifetime: 1w
  227. interval: 1d
  228. - shortest_max_lifetime: 1w
  229. interval: 2d
  230. </code></pre>
  231. <p>In this example, we define three jobs:</p>
  232. <ul>
  233. <li>one that runs twice a day (every 12 hours) and purges events in rooms
  234. which policy's <code>max_lifetime</code> is lower or equal to 3 days.</li>
  235. <li>one that runs once a day and purges events in rooms which policy's
  236. <code>max_lifetime</code> is between 3 days and a week.</li>
  237. <li>one that runs once every 2 days and purges events in rooms which
  238. policy's <code>max_lifetime</code> is greater than a week.</li>
  239. </ul>
  240. <p>Note that this example is tailored to show different configurations and
  241. features slightly more jobs than it's probably necessary (in practice, a
  242. server admin would probably consider it better to replace the two last
  243. jobs with one that runs once a day and handles rooms which
  244. policy's <code>max_lifetime</code> is greater than 3 days).</p>
  245. <p>Keep in mind, when configuring these jobs, that a purge job can become
  246. quite heavy on the server if it targets many rooms, therefore prefer
  247. having jobs with a low interval that target a limited set of rooms. Also
  248. make sure to include a job with no minimum and one with no maximum to
  249. make sure your configuration handles every policy.</p>
  250. <p>As previously mentioned in this documentation, while a purge job that
  251. runs e.g. every day means that an expired event might stay in the
  252. database for up to a day after its expiry, Synapse hides expired events
  253. from clients as soon as they expire, so the event is not visible to
  254. local users between its expiry date and the moment it gets purged from
  255. the server's database.</p>
  256. <h3 id="lifetime-limits"><a class="header" href="#lifetime-limits">Lifetime limits</a></h3>
  257. <p>Server admins can set limits on the values of <code>max_lifetime</code> to use when
  258. purging old events in a room. These limits can be defined under the
  259. <code>retention</code> option in the configuration file:</p>
  260. <pre><code class="language-yaml">allowed_lifetime_min: 1d
  261. allowed_lifetime_max: 1y
  262. </code></pre>
  263. <p>The limits are considered when running purge jobs. If necessary, the
  264. effective value of <code>max_lifetime</code> will be brought between
  265. <code>allowed_lifetime_min</code> and <code>allowed_lifetime_max</code> (inclusive).
  266. This means that, if the value of <code>max_lifetime</code> defined in the room's state
  267. is lower than <code>allowed_lifetime_min</code>, the value of <code>allowed_lifetime_min</code>
  268. will be used instead. Likewise, if the value of <code>max_lifetime</code> is higher
  269. than <code>allowed_lifetime_max</code>, the value of <code>allowed_lifetime_max</code> will be
  270. used instead.</p>
  271. <p>In the example above, we ensure Synapse never deletes events that are less
  272. than one day old, and that it always deletes events that are over a year
  273. old.</p>
  274. <p>If a default policy is set, and its <code>max_lifetime</code> value is lower than
  275. <code>allowed_lifetime_min</code> or higher than <code>allowed_lifetime_max</code>, the same
  276. process applies.</p>
  277. <p>Both parameters are optional; if one is omitted Synapse won't use it to
  278. adjust the effective value of <code>max_lifetime</code>.</p>
  279. <p>Like other settings in this section, these parameters can be expressed
  280. either as a duration or as a number of milliseconds.</p>
  281. <h2 id="room-configuration"><a class="header" href="#room-configuration">Room configuration</a></h2>
  282. <p>To configure a room's message retention policy, a room's admin or
  283. moderator needs to send a state event in that room with the type
  284. <code>m.room.retention</code> and the following content:</p>
  285. <pre><code class="language-json">{
  286. &quot;max_lifetime&quot;: ...
  287. }
  288. </code></pre>
  289. <p>In this event's content, the <code>max_lifetime</code> parameter has the same
  290. meaning as previously described, and needs to be expressed in
  291. milliseconds. The event's content can also include a <code>min_lifetime</code>
  292. parameter, which has the same meaning and limited support as previously
  293. described.</p>
  294. <p>Note that over every server in the room, only the ones with support for
  295. message retention policies will actually remove expired events. This
  296. support is currently not enabled by default in Synapse.</p>
  297. <h2 id="note-on-reclaiming-disk-space"><a class="header" href="#note-on-reclaiming-disk-space">Note on reclaiming disk space</a></h2>
  298. <p>While purge jobs actually delete data from the database, the disk space
  299. used by the database might not decrease immediately on the database's
  300. host. However, even though the database engine won't free up the disk
  301. space, it will start writing new data into where the purged data was.</p>
  302. <p>If you want to reclaim the freed disk space anyway and return it to the
  303. operating system, the server admin needs to run <code>VACUUM FULL;</code> (or
  304. <code>VACUUM;</code> for SQLite databases) on Synapse's database (see the related
  305. <a href="https://www.postgresql.org/docs/current/sql-vacuum.html">PostgreSQL documentation</a>).</p>
  306. </main>
  307. <nav class="nav-wrapper" aria-label="Page navigation">
  308. <!-- Mobile navigation buttons -->
  309. <a rel="prev" href="user_directory.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
  310. <i class="fa fa-angle-left"></i>
  311. </a>
  312. <a rel="next" href="modules/index.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
  313. <i class="fa fa-angle-right"></i>
  314. </a>
  315. <div style="clear: both"></div>
  316. </nav>
  317. </div>
  318. </div>
  319. <nav class="nav-wide-wrapper" aria-label="Page navigation">
  320. <a rel="prev" href="user_directory.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
  321. <i class="fa fa-angle-left"></i>
  322. </a>
  323. <a rel="next" href="modules/index.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
  324. <i class="fa fa-angle-right"></i>
  325. </a>
  326. </nav>
  327. </div>
  328. <script type="text/javascript">
  329. window.playground_copyable = true;
  330. </script>
  331. <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
  332. <script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
  333. <script src="searcher.js" type="text/javascript" charset="utf-8"></script>
  334. <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
  335. <script src="highlight.js" type="text/javascript" charset="utf-8"></script>
  336. <script src="book.js" type="text/javascript" charset="utf-8"></script>
  337. <!-- Custom JS scripts -->
  338. <script type="text/javascript" src="docs/website_files/table-of-contents.js"></script>
  339. <script type="text/javascript" src="docs/website_files/version-picker.js"></script>
  340. <script type="text/javascript" src="docs/website_files/version.js"></script>
  341. </body>
  342. </html>