diff --git a/docs/backend/deprecation.md b/docs/backend/deprecation.md
new file mode 100644
index 000000000..80a0a98e6
--- /dev/null
+++ b/docs/backend/deprecation.md
@@ -0,0 +1,318 @@
+---
+myst:
+ html_meta:
+ "description": "A guide how to do deprecations, including Python, ZCML and templates in Plone."
+ "property=og:description": "A guide how to do deprecations, including Python, ZCML and templates in Plone."
+ "property=og:title": "Deprecation"
+ "keywords": "deprecation, zcml, template, jbot"
+---
+
+(backend-deprecation-label)=
+# Deprecation
+
+## Introduction
+
+This document describes rationales, configuration and best practices of deprecations in Plone, Zope and Python.
+It is meant as a styleguide on how to apply deprecations in Plone core packages.
+It also has a value as a general overview on how to deprecate in Python.
+
+
+### Why Deprecation
+
+At some point we:
+
+- need to get rid of old code,
+- want to unify API style (consistent API),
+- fix typos in namings,
+- move code or templates around (inside package or to another package).
+
+While refactoring code, moving modules, functions, classes and methods is often needed.
+To not break third party code imports from the old place or usage of old functions/ methods must work for while.
+Deprecated methods are usually removed with the next major release of Plone.
+
+Following the [semantic versioning guideline](https://semver.org) is recommended.
+
+### Help Programmers, No annoyance
+
+The developers should use code deprecations to support the consumers of the code.
+From their point of view, Plone core code is an API to them.
+Any change is annoying to them anyway, but they feel better if deprecation warnings are telling them what to do.
+
+Deprecations must always log at level *warning* and have to answers the question:
+
+**"Why is the code gone from the old place? What to do instead?"**
+
+A short message is enough., i.e.:
+
+- "Replaced by new API xyz, found at abc.cde".,
+- "Moved to xyz, because of abc.",
+- "Name had a typo, new name is "xyz".
+
+All logging has to be done once, i.e. on first usage or first import.
+It must not flood the logs.
+
+### Use Cases
+
+Renaming
+
+: We may want to rename classes, methods, functions or global or class variables in order to get a more consistent API or because of a typo, etc.
+ We never just rename, we always provide a deprecated version logging a verbose deprecation warning with information where to
+ import from in future.
+
+Moving a module, class, function, etc to another place
+
+: For some reason, i.e. merging packages, consistent API or resolving cirular import problems, we need to move code around.
+ When imported from the old place it logs a verbose deprecation warning with information where to import from in future.
+
+Deprecation of a whole package
+
+: A whole [package](https://docs.python.org/3/tutorial/modules.html#packages)
+
+ - all imports still working, logging deprecation warnings on first import
+ - ZCML still exists, but is empty (or includes the zcml from the new place if theres no auto import (i.e. for meta.zcml).
+
+Deprecation of a whole released/ installable package.
+
+: We will provide a last major release with no 'real' code, only backward compatible (bbb) imports of public API are provided.
+ This will be done the way described above for a whole package.
+ The README clearly states why it was moved and where to find the code now.
+
+Deprecation of a GenericSetup profile
+
+: They may got renamed for consistency or are superfluos after an update.
+ Code does not need to break to support this.
+
+## Enable Deprecation Warnings
+
+### Zope
+
+Zope does configure logging and warnings, so the steps below (under section Python) are not needed.
+
+Using `plone.recipe.zope2instance` add the option `deprecation-warnings = on` to the buildouts `[instance]` section.
+
+```ini
+[buildout]
+parts = instance
+
+[instance]
+recipe = plone.recipe.zope2instance
+...
+deprecation-warnings = on
+...
+```
+
+This adds this line to the `zope.conf` file:
+
+```
+debug-mode on
+```
+
+Without the recipe this can be set manually as well:
+In `zope.conf` custom filters for warnings can be defined.
+
+```xml
+...
+
+ action always
+ category exceptions.DeprecationWarning
+
+...
+```
+
+### Python
+
+Enable Warnings
+
+: Warnings are written to `stderr` by default, but `DeprecationWarning` output is surpressed by default.
+
+ Output can be enabled by starting the Python interpreter with the [-W \[all|module|once\]](https://docs.python.org/3/using/cmdline.html#cmdoption-W) option.
+
+ It is possible to enable output in code too:
+
+ ```python
+ import warnings
+ warnings.simplefilter("module")
+ ```
+
+Configure Logging
+
+: Once output is enabled it is possible to [redirect warnings to the logger](https://docs.python.org/3/library/logging.html#logging.captureWarnings):
+
+ ```python
+ import logging
+ logging.captureWarnings(True)
+ ```
+
+### Running tests
+
+In Plone tests deprecation warnings are not shown by default.
+The `zope.conf` setting is not taken into account.
+
+In order to enable deprecation warnings,
+the Python way with the `-W` command option must to be used.
+
+Given youre using a modern buildout with virtualenv as recommended,
+the call looks like so:
+
+```bash
+./bin/python -W module ./bin/test
+```
+
+## Deprecation Best Practice
+
+### Vanilla Deprecation Messages
+
+Python offers a built-in `DeprecationWarning` which can be issued using standard libraries `warnings` module.
+
+For details read the [official documentation about warnings](https://docs.python.org/3/library/warnings.html).
+
+In short it works like so
+
+```python
+import warnings
+warnings.warn('deprecated', DeprecationWarning)
+```
+
+### Moving Whole Modules
+
+Given a package `old.pkg` with a module `foo.py` need to be moved to a package `new.pkg` as `bar.py`.
+
+[zope.deprecation Moving modules](https://zopedeprecation.readthedocs.io/en/latest/api.html#moving-modules) offers a helper.
+
+1. Move the `foo.py` as `bar.py` to the `new.pkg`.
+2. At the old place create a new `foo.py` and add to it
+
+```python
+from zope.deprecation import moved
+moved('new.pkg.bar', 'Version 2.0')
+```
+
+Now you can still import the namespace from `bar` at the old place, but get a deprecation warning:
+
+> DeprecationWarning: old.pkg.foo has moved to new.pkg.bar.
+> Import of old.pkg.foo will become unsupported in Version 2.0
+
+### Moving Whole Packages
+
+This is the same as moving a module, just create for each module a file.
+
+### Deprecating methods and properties
+
+You can use the `@deprecate` decorator from [zope.deprecation Deprecating methods and properties](https://zopedeprecation.readthedocs.io/en/latest/api.html#deprecating-methods-and-properties) to deprecate methods in a module:
+
+```python
+from zope.deprecation import deprecate
+
+@deprecate('Old method is no longer supported, use new_method instead.')
+def old_method():
+ return 'some value'
+```
+
+The `deprecated` wrapper method is for deprecating properties:
+
+```python
+from zope.deprecation import deprecated
+
+foo = None
+foo = deprecated(foo, 'foo is no more, use bar instead')
+```
+
+### Moving functions and classes
+
+Given we have a Python file at `old/foo/bar.py` and want to move some classes or functions to `new/baz/baaz.py`.
+
+Here `zope.deferredimport` offers a deprecation helper.
+It also avoids circular imports on initialization time.
+
+```python
+import zope.deferredimport
+zope.deferredimport.initialize()
+
+zope.deferredimport.deprecated(
+ "Import from new.baz.baaz instead",
+ SomeOldClass='new.baz:baaz.SomeMovedClass',
+ some_old_function='new.baz:baaz.some_moved_function',
+)
+
+def some_function_which_is_not_touched_at_all():
+ pass
+```
+
+### Deprecating a GenericSetup profile
+
+Starting with GenericSetup 1.8.2 (part of Plone > 5.0.2) the `post_handler` attribute in ZCML can be used to call a function after the profile was applied.
+We use this feature to issue a warning.
+
+First we register the same profile twice. Under the new name and under the old name:
+
+```xml
+
+
+
+```
+
+And in `setuphandlers.py` add a function:
+
+```python
+import warnings
+
+def deprecate_profile_some_confusing_name(tool):
+ warnings.warn(
+ 'The profile with id "some_confusing_name" was renamed to "default".',
+ DeprecationWarning
+ )
+```
+
+### Deprecating a template position
+
+Sometimes we need to move templates to new locations. Since addons often use [z3c.jbot](https://github.com/zopefoundation/z3c.jbot) to override templates by their position, we need to point them to the new position as well as make sure that the override still works with the old position.
+
+
+To deprecate a package:
+
+1. In the old package folders `__init__.py` add a dictionary `jbot_deprecations` that maps the old template locations to their new counterparts, e.g.:
+
+```python
+jbot_deprecations = {
+ "plone.locking.browser.info.pt": "plone.app.layout.viewlets.info.pt"
+}
+```
+
+2. Add this deprecation snippet to the package `configure.zcml` file:
+
+```{code-block} xml
+:emphasize-lines: 6,9-12
+:linenos:
+
+
+
+
+
+
+
+```
+
+If a `z3c.jbot` version that supports deprecation is found, trying to override the template with the old location will trigger a deprecation warning that will instruct the user to rename its override file.
diff --git a/docs/backend/index.md b/docs/backend/index.md
index 3e7dd3278..9411e26f7 100644
--- a/docs/backend/index.md
+++ b/docs/backend/index.md
@@ -22,6 +22,7 @@ behaviors
configuration-registry
content-types/index
control-panels
+deprecation
fields
global-utils
indexing