<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Configuration on back(d)</title><link>https://fernandezvara.github.io/backd/docs/build/configuration/</link><description>Recent content in Configuration on back(d)</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://fernandezvara.github.io/backd/docs/build/configuration/index.xml" rel="self" type="application/rss+xml"/><item><title>Data model (CONFIG_DIR)</title><link>https://fernandezvara.github.io/backd/docs/build/configuration/config-dir/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/configuration/config-dir/</guid><description>&lt;p&gt;The data model is a directory tree under &lt;code&gt;CONFIG_DIR&lt;/code&gt;, loaded once at startup. Directories define realms and databases, and a &lt;code&gt;schema.json&lt;/code&gt; defines a collection.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$CONFIG_DIR/&amp;lt;realm&amp;gt;/
 realm.yaml # required — realm settings
 email/&amp;lt;kind&amp;gt;/ # optional — email templates (see Functions → Email)
 app-config/ # optional — app configuration: schema.json and rules.yaml
 &amp;lt;database&amp;gt;/&amp;lt;collection&amp;gt;/
 schema.json # required — JSON Schema draft 2020-12
 indexes.json # optional — index declarations
 collection.yaml # optional — access rules, file fields, soft delete, erase policy
 rules.test.yaml # optional — tests of the rules (`backd rules test`)
 &amp;lt;database&amp;gt;/_functions/ # optional — server-side functions
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Each directory under &lt;code&gt;CONFIG_DIR&lt;/code&gt; is a &lt;strong&gt;realm&lt;/strong&gt;. It must contain a &lt;a href="../realm/"&gt;&lt;code&gt;realm.yaml&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Each directory inside a realm is a &lt;strong&gt;database&lt;/strong&gt;, stored in the MongoDB database &lt;code&gt;&amp;lt;realm&amp;gt;__&amp;lt;database&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Each directory inside a database is a &lt;strong&gt;collection&lt;/strong&gt;, stored in a MongoDB collection of the same name. It must contain a &lt;code&gt;schema.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A realm&amp;rsquo;s &lt;code&gt;email&lt;/code&gt; folder holds its &lt;a href="../../functions/email/#templates"&gt;email templates&lt;/a&gt;, &lt;code&gt;pages&lt;/code&gt; is reserved for the pages backd will serve, &lt;code&gt;push&lt;/code&gt; holds &lt;a href="../../push/"&gt;push templates&lt;/a&gt; and &lt;code&gt;consents&lt;/code&gt; holds the &lt;a href="../../auth/consents/"&gt;consent texts&lt;/a&gt;: none is a database, so they are never read as one and can&amp;rsquo;t be database names.&lt;/li&gt;
&lt;li&gt;A realm&amp;rsquo;s &lt;code&gt;app-config&lt;/code&gt; folder declares its &lt;a href="#app-configuration"&gt;app configuration&lt;/a&gt;, and is not a database either.&lt;/li&gt;
&lt;li&gt;A database&amp;rsquo;s &lt;code&gt;_functions&lt;/code&gt; directory holds its &lt;a href="../../functions/"&gt;functions&lt;/a&gt;, not a collection.&lt;/li&gt;
&lt;li&gt;Other plain files at the realm and database levels are ignored, as are hidden entries (names starting with &lt;code&gt;.&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Changing the config requires a restart — except with &lt;code&gt;BACKD_DEV=true&lt;/code&gt;, which reloads it live (see &lt;a href="../../functions/testing/#dev-mode"&gt;Dev mode&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="starting-from-a-template"&gt;Starting from a template&lt;a class="hd-anchor" href="#starting-from-a-template" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;backd template&lt;/code&gt; writes commented starter files, so you don&amp;rsquo;t have to start from an empty directory. It only needs &lt;code&gt;CONFIG_DIR&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>App configuration</title><link>https://fernandezvara.github.io/backd/docs/build/configuration/app-config/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/configuration/app-config/</guid><description>&lt;p&gt;App configuration is one realm-level configuration for your client apps: feature flags, maintenance switches, promotions, limits. It is declared like collections (a JSON Schema and read rules), changed at runtime by administrators and functions only, and read by apps through one endpoint with caching.&lt;/p&gt;
&lt;p&gt;It is not a secrets store (see &lt;a href="#no-secrets-no-encryption"&gt;No secrets, no encryption&lt;/a&gt;), not a content store (the whole configuration is at most 64 KiB), and not a targeting system: there are no per-user or percentage rollouts. Time-based changes are your own &lt;a href="../../functions/cron/"&gt;cron functions&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Realm settings (realm.yaml)</title><link>https://fernandezvara.github.io/backd/docs/build/configuration/realm/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/configuration/realm/</guid><description>&lt;p&gt;Every realm directory must contain a &lt;code&gt;realm.yaml&lt;/code&gt;. It holds the settings that apply to the whole realm: its users, how they sign in, and which browser origins may call it.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$CONFIG_DIR/&amp;lt;realm&amp;gt;/realm.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If a realm has no &lt;code&gt;realm.yaml&lt;/code&gt;, &lt;code&gt;backd&lt;/code&gt; refuses to start and names the realm. Create a commented starter file with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./config backd template realm --realm &amp;lt;realm&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="example"&gt;Example&lt;a class="hd-anchor" href="#example" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;signup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;invite&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;idle_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;14d&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max_lifetime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;60d&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;min_length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;origins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;https://app.example.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;http://localhost:5173&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Manages users and invitations&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ops@example.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;lead@example.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Can publish articles&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An empty file, or one with only comments, is valid: every key has a default.&lt;/p&gt;</description></item><item><title>Custom ids</title><link>https://fernandezvara.github.io/backd/docs/build/configuration/custom-ids/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/configuration/custom-ids/</guid><description>&lt;p&gt;By default &lt;code&gt;backd&lt;/code&gt; generates the id of every document. A collection can instead take it from the client, for ids that mean something: an invoice number, a reference from another system, or the user&amp;rsquo;s own id for one document per user. This page is about &lt;strong&gt;when to use that and how to do it safely&lt;/strong&gt;; the declaration is in &lt;a href="../config-dir/#custom-ids"&gt;&lt;code&gt;collection.yaml&lt;/code&gt;&lt;/a&gt;, and the requests and errors are in &lt;a href="../../api/documents/#custom-ids"&gt;Create&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="when-to-use-them"&gt;When to use them&lt;a class="hd-anchor" href="#when-to-use-them" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Use&lt;/th&gt;
 &lt;th&gt;Why&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;One document per user (profile, settings, preferences)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;custom_id: user&lt;/code&gt; makes the id the user&amp;rsquo;s own, so the document is found with &lt;code&gt;GET …/profiles/&amp;lt;user id&amp;gt;&lt;/code&gt;, nothing else is needed to keep it unique, and backd refuses an id that isn&amp;rsquo;t the caller&amp;rsquo;s&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;A number or reference that exists outside backd&lt;/td&gt;
 &lt;td&gt;The document is addressed by the number you already print and receive; a second one with the same number is refused&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Human-readable keys of reference data (&lt;code&gt;EUR&lt;/code&gt;, &lt;code&gt;de-DE&lt;/code&gt;)&lt;/td&gt;
 &lt;td&gt;Fixed vocabularies you create and own&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Don&amp;rsquo;t use them for anything that might &lt;strong&gt;change&lt;/strong&gt; (an id never changes), for anything that holds &lt;strong&gt;personal data&lt;/strong&gt; (see &lt;a href="#personal-data-in-ids"&gt;below&lt;/a&gt;), or only to avoid a unique index: a unique field in &lt;code&gt;indexes.json&lt;/code&gt; works with generated ids and can change.&lt;/p&gt;</description></item><item><title>Schema validation</title><link>https://fernandezvara.github.io/backd/docs/build/configuration/validation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://fernandezvara.github.io/backd/docs/build/configuration/validation/</guid><description>&lt;p&gt;Every collection&amp;rsquo;s &lt;code&gt;schema.json&lt;/code&gt; is enforced at two levels.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;API level (authoritative).&lt;/strong&gt; Every write is validated against the full JSON Schema draft 2020-12 before it reaches the database. Failures return &lt;code&gt;400&lt;/code&gt; with one entry per failing field.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database level (safety net).&lt;/strong&gt; The same schema is translated into a MongoDB &lt;code&gt;$jsonSchema&lt;/code&gt; collection validator. This protects the data from writes that bypass the API. MongoDB&amp;rsquo;s dialect is older and smaller, so the translation covers a subset of the schema.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="translation-to-mongodb"&gt;Translation to MongoDB&lt;a class="hd-anchor" href="#translation-to-mongodb" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;JSON Schema&lt;/th&gt;
 &lt;th&gt;MongoDB &lt;code&gt;$jsonSchema&lt;/code&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;type: string&lt;/code&gt; / &lt;code&gt;boolean&lt;/code&gt; / &lt;code&gt;object&lt;/code&gt; / &lt;code&gt;array&lt;/code&gt; / &lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;bsonType: string&lt;/code&gt; / &lt;code&gt;bool&lt;/code&gt; / &lt;code&gt;object&lt;/code&gt; / &lt;code&gt;array&lt;/code&gt; / &lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;type: integer&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;bsonType: [int, long, double]&lt;/code&gt; plus &lt;code&gt;multipleOf: 1&lt;/code&gt;, unless the schema sets its own &lt;code&gt;multipleOf&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;type: number&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;bsonType: [int, long, double, decimal]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;const: v&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;enum: [v]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;exclusiveMinimum: n&lt;/code&gt; / &lt;code&gt;exclusiveMaximum: n&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;minimum&lt;/code&gt; / &lt;code&gt;maximum: n&lt;/code&gt; plus &lt;code&gt;exclusiveMinimum&lt;/code&gt; / &lt;code&gt;exclusiveMaximum: true&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;properties&lt;/code&gt;, &lt;code&gt;required&lt;/code&gt;, &lt;code&gt;enum&lt;/code&gt;, &lt;code&gt;minimum&lt;/code&gt;, &lt;code&gt;maximum&lt;/code&gt;, &lt;code&gt;multipleOf&lt;/code&gt;, &lt;code&gt;minLength&lt;/code&gt;, &lt;code&gt;maxLength&lt;/code&gt;, &lt;code&gt;pattern&lt;/code&gt;, &lt;code&gt;items&lt;/code&gt;, &lt;code&gt;minItems&lt;/code&gt;, &lt;code&gt;maxItems&lt;/code&gt;, &lt;code&gt;uniqueItems&lt;/code&gt;, &lt;code&gt;additionalProperties&lt;/code&gt;, &lt;code&gt;minProperties&lt;/code&gt;, &lt;code&gt;maxProperties&lt;/code&gt;, &lt;code&gt;allOf&lt;/code&gt;, &lt;code&gt;anyOf&lt;/code&gt;, &lt;code&gt;oneOf&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;copied as-is (subschemas translated recursively)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;Annotations (&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;examples&lt;/code&gt;, &lt;code&gt;$comment&lt;/code&gt;, …) are dropped silently.&lt;/li&gt;
&lt;li&gt;Any other keyword (for example &lt;code&gt;format&lt;/code&gt;, &lt;code&gt;$ref&lt;/code&gt;/&lt;code&gt;$defs&lt;/code&gt;, &lt;code&gt;prefixItems&lt;/code&gt;, &lt;code&gt;unevaluatedProperties&lt;/code&gt; or &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;then&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;) is left out of the database validator and logged at &lt;code&gt;info&lt;/code&gt; level with its location. The API level still enforces it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="finding-documents-that-no-longer-match"&gt;Finding documents that no longer match&lt;a class="hd-anchor" href="#finding-documents-that-no-longer-match" aria-hidden="true"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;A schema is enforced when a document is &lt;strong&gt;written&lt;/strong&gt;. Documents stored before you changed the schema are not touched, and MongoDB is set to leave them alone (&lt;code&gt;validationLevel: moderate&lt;/code&gt;): a collection can hold documents that would be refused today. A &lt;em&gt;schema check&lt;/em&gt; lists them. It reads every stored document, validates it with the same full validator the API uses on a write (so it also sees the keywords MongoDB&amp;rsquo;s translation leaves out, such as &lt;code&gt;format&lt;/code&gt;), and reports the ones that fail. It &lt;strong&gt;never writes&lt;/strong&gt; anything.&lt;/p&gt;</description></item></channel></rss>