{"id":55,"date":"2026-10-01T16:28:42","date_gmt":"2026-10-01T16:28:42","guid":{"rendered":"https:\/\/pomax-v3.weeltec.com\/?p=55"},"modified":"2026-10-01T16:28:42","modified_gmt":"2026-10-01T16:28:42","slug":"patch-cadence-policy-not-a-plan","status":"publish","type":"post","link":"https:\/\/pomax-v3.weeltec.com\/?p=55","title":{"rendered":"Patch Cadence: Why Monthly Is a Policy, Not a Plan"},"content":{"rendered":"<div class=\"wt-post\">\n<style>.wt-post { --wt-bg: #0A0C0F; --wt-bg-2: #0E1116; --wt-surface: #12161C; --wt-line: #1F252E; --wt-line-strong: #2B333E; --wt-text: #E9ECEF; --wt-muted: #98A2AD; --wt-accent: #B9F24D; --wt-accent-hover: #C8FF5E; --wt-accent-dim: rgba(185, 242, 77, 0.10); --wt-accent-line: rgba(185, 242, 77, 0.25); --wt-danger: #F07A6B; --wt-ok: #7ED99A; --wt-sans: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif; --wt-mono: ui-monospace, \"Cascadia Code\", \"JetBrains Mono\", \"SF Mono\", Menlo, Consolas, monospace; --wt-radius: 4px; --wt-h1: var(--wt-text); --wt-h2: var(--wt-text); --wt-h3: var(--wt-text); box-sizing: border-box; background: var(--wt-bg); color: var(--wt-text); font-family: var(--wt-sans); font-size: 1rem; line-height: 1.7; padding: clamp(1.75rem, 4vw, 3rem); border: 1px solid var(--wt-line); border-radius: 0; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } .wt-post *, .wt-post *::before, .wt-post *::after { box-sizing: border-box; } .wt-post ::selection { background: var(--wt-accent); color: var(--wt-bg); } .wt-post.wt-post p { color: var(--wt-text); font-family: var(--wt-sans); font-size: 1rem; line-height: 1.7; margin: 0 0 1.15rem; max-width: 68ch; } .wt-post.wt-post p:last-child { margin-bottom: 0; } .wt-post.wt-post h1, .wt-post.wt-post h2, .wt-post.wt-post h3, .wt-post.wt-post h4, .wt-post.wt-post h5, .wt-post.wt-post h6 { font-family: var(--wt-sans); font-weight: 700; letter-spacing: -0.025em; line-height: 1.15; text-wrap: balance; } .wt-post.wt-post h2 { color: var(--wt-h2); font-size: clamp(1.45rem, 3vw, 2rem); margin: 2.4rem 0 0.9rem; display: flex; align-items: baseline; gap: 0.6rem; } .wt-post.wt-post h2::before { content: \"\"; flex: none; width: 8px; height: 8px; background: var(--wt-accent); transform: translateY(-2px); } .wt-post.wt-post h3 { color: var(--wt-h3); font-size: 1.15rem; font-weight: 650; margin: 1.8rem 0 0.7rem; padding-left: 0.85rem; border-left: 2px solid var(--wt-accent-line); } .wt-post.wt-post h2:first-child, .wt-post.wt-post h3:first-child { margin-top: 0; } .wt-post.wt-post strong { color: #FFFFFF; font-weight: 650; } .wt-post.wt-post em { color: var(--wt-muted); font-style: italic; } .wt-post.wt-post a { color: var(--wt-accent); text-decoration: none; border-bottom: 1px solid var(--wt-accent-line); transition: color 0.15s ease, border-color 0.15s ease; } .wt-post.wt-post a:hover { color: var(--wt-accent-hover); border-bottom-color: var(--wt-accent-hover); } .wt-post.wt-post ul, .wt-post.wt-post ol { margin: 0 0 1.3rem; padding: 0; list-style: none; max-width: 68ch; } .wt-post.wt-post li { position: relative; padding-left: 1.6rem; margin-bottom: 0.55rem; color: var(--wt-text); line-height: 1.65; } .wt-post.wt-post ul > li::before { content: \"\\25AE\"; color: var(--wt-accent); position: absolute; left: 0; top: 0; font-size: 0.85em; line-height: 1.65; } .wt-post.wt-post ol { counter-reset: wt-li; } .wt-post.wt-post ol > li { counter-increment: wt-li; } .wt-post.wt-post ol > li::before { content: counter(wt-li) \".\"; font-family: var(--wt-mono); font-size: 0.8em; color: var(--wt-accent); position: absolute; left: 0; top: 0; line-height: 1.9; } .wt-post.wt-post blockquote { margin: 1.8rem 0; padding: 1.1rem 1.4rem; background: var(--wt-accent-dim); border-left: 2px solid var(--wt-accent); border-radius: 0; color: var(--wt-text); font-size: 1.05rem; font-style: normal; line-height: 1.6; } .wt-post.wt-post blockquote p { margin: 0; color: var(--wt-text); font-style: normal; } .wt-post.wt-post blockquote::before { content: none; } .wt-post.wt-post code, .wt-post.wt-post kbd, .wt-post.wt-post pre { font-family: var(--wt-mono); font-size: 0.88em; } .wt-post.wt-post code { background: var(--wt-surface); border: 1px solid var(--wt-line); border-radius: var(--wt-radius); padding: 0.1em 0.4em; color: var(--wt-accent); } .wt-post.wt-post pre { background: #0C0F13; border: 1px solid var(--wt-line-strong); border-radius: var(--wt-radius); padding: 1.1rem 1.25rem; overflow-x: auto; color: var(--wt-text); line-height: 1.7; margin: 0 0 1.3rem; } .wt-post.wt-post pre code { background: none; border: 0; padding: 0; color: inherit; } .wt-post.wt-post hr { border: 0; border-top: 1px solid var(--wt-line); margin: 2.2rem 0; } .wt-post.wt-post img { max-width: 100%; height: auto; border-radius: var(--wt-radius); border: 1px solid var(--wt-line); } @media (max-width: 640px) { .wt-post.wt-post h2 { font-size: 1.35rem; } .wt-post.wt-post blockquote { padding: 0.9rem 1.1rem; } } @media (prefers-reduced-motion: reduce) { .wt-post.wt-post a { transition: none; } }<\/style>\n<p>\"We patch monthly\" is a cadence, not a plan. It tells you the interval and nothing else \u2014 not which systems, not who verifies the result, and not what happens when the job fails silently on a Sunday.<\/p>\n<p>A plan answers the harder questions: what gets patched, in what order, with what evidence, and what you do when a patch lands badly. The interval is the easy half.<\/p>\n<h2>Why a single cadence fails<\/h2>\n<p>Monthly is a compromise between two risks that have almost nothing in common. An internet-facing VPN appliance with a known exploited vulnerability is not the same problem as an internal reporting box running a local-only service. Put both on the same calendar and the urgent one waits while the harmless one gets rebooted.<\/p>\n<p>The timelines make this concrete. Once a high-profile CVE is weaponised, working exploits usually appear within 48 hours, and mass scanning starts sooner than that. That is well inside a monthly window. The vulnerability you can safely defer for two weeks is the one sitting behind a firewall with no reachable authentication surface.<\/p>\n<p>So the real question is not how often you patch. It is how fast you can patch this class of system, and whether you can prove that you did.<\/p>\n<h2>Tier by exposure, not by calendar<\/h2>\n<h3>Tier 1: internet-facing<\/h3>\n<p>Anything with a public listener \u2014 web servers, load balancers, VPN concentrators, mail gateways, exposed APIs. These patch against the clock, not the calendar. A critical vulnerability here is handled within 24 to 72 hours, out of band, with a reboot budget the business has already accepted in writing.<\/p>\n<h3>Tier 2: internal and service infrastructure<\/h3>\n<p>Databases, message queues, internal APIs, and CI runners holding deploy credentials. These matter, but the exposure window is narrower because the attacker needs a foothold first. A weekly or fortnightly window is usually defensible.<\/p>\n<h3>Tier 3: endpoints and long-tail hosts<\/h3>\n<p>Developer workstations, test boxes, and forgotten VMs. Patch monthly, but keep an inventory, because the real risk in this tier is a host nobody remembers owning or patching at all.<\/p>\n<h2>The loop every tier runs<\/h2>\n<p>The timer changes by tier. The loop does not.<\/p>\n<ul>\n<li><strong>Detect.<\/strong> Feed a scanner and vendor advisories into an inventory that reflects reality, not the spreadsheet from last year.<\/li>\n<li><strong>Stage.<\/strong> Apply the patch to a representative non-production host first, then let it bake for at least one business day.<\/li>\n<li><strong>Apply.<\/strong> Roll out in waves, smallest blast radius first, inside a maintenance window the stakeholders know about.<\/li>\n<li><strong>Verify.<\/strong> Confirm with the package manager and an independent scan \u2014 an agent reporting success is not proof of anything.<\/li>\n<li><strong>Record.<\/strong> Log host, package, version, ticket, and timestamp. This artefact is what turns a cadence into evidence.<\/li>\n<\/ul>\n<h2>Plan for the patch that breaks production<\/h2>\n<p>Some patches break things, and pretending otherwise is how teams quietly stop patching. Every tier needs a rollback path that has been tested, not a theoretical one: package caches kept on the host, a snapshot taken immediately before the window, and a written rule for who can call a rollback without convening a meeting. If a patch requires a restart, schedule it and tell people \u2014 a surprise reboot during peak traffic is how an incident starts.<\/p>\n<blockquote>\n<p>A patch policy nobody can audit is a mood, not a control.<\/p>\n<\/blockquote>\n<h2>How Weeltec runs this<\/h2>\n<p>On our server management engagements, every host is tagged by exposure tier in configuration management, and patching is driven from that tag rather than a manual list someone maintains by hand. Out-of-band critical patching is wired into the same alerting as production incidents, and the monthly report is generated from logs rather than memory. When an auditor asks you to show every host and its last patch date, the answer should be a query, not a project.<\/p>\n<h2>The rule<\/h2>\n<p>Pick your cadence, then write down what happens before, during, and after each window. Tier the systems by exposure. Test the rollback. Keep the evidence.<\/p>\n<p>Monthly is fine as a default. It is not a plan until it has an owner, a tier, and a log line behind it.<\/p>\n<p><em>Weeltec runs servers and infrastructure for teams that can't afford surprise outages. If your patch process lives in someone's head, <a href=\"https:\/\/weeltec.com\/#contact\">get a quote<\/a> and we'll put it in writing.<\/em><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Monthly patching is an interval, not a plan. Here is how to tier hosts by exposure, run a repeatable patch loop, and keep the evidence an auditor will eventually ask for.<\/p>\n","protected":false},"author":1,"featured_media":52,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[6,30,28,29],"class_list":["post-55","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server-management","tag-devops","tag-maintenance-windows","tag-patching","tag-server-management"],"_links":{"self":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts\/55","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=55"}],"version-history":[{"count":2,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts\/55\/revisions"}],"predecessor-version":[{"id":83,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts\/55\/revisions\/83"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/media\/52"}],"wp:attachment":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=55"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=55"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=55"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}