[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f-a90GoocPcBZj1kGYJW0yYvurWrkInD2JJDxPCH0UIE":3},{"item":4},{"id":5,"idKnowledge":6,"idDomain":7,"idCluster":8,"kindOverride":9,"slug":10,"title":11,"description":12,"bodyMarkdown":13,"bodyHtml":14,"author":15,"date":16,"createdAt":17,"topics":18,"image":25,"hasDownload":26,"fileName":27,"youtubeId":28,"domainCrumb":29,"clusterCrumb":32},"342","C0E278EF-101D-0C4B-9519-72AD54FE695B","8F2761C8-348C-C649-BC16-18822CE2D198","0CABB9FC-2F40-2843-9F90-CA5BDC0926C0","article","how-to-retire-obsolete-functionality-safely","How to retire obsolete functionality safely","A practical guide to removing outdated modules, scripts, and features from business software without breaking things nobody remembered were connected.","Every piece of business software eventually collects features nobody uses anymore. A discount calculator built for a promotion that ended three years ago. A \"print fax cover sheet\" button in a FileMaker system that still runs, technically, even though the fax machine was unplugged in 2019. An old API connector to a supplier you stopped working with, still firing a scheduled script every night. Nobody wants to touch it, because nobody is 100% sure what else it's quietly attached to.\n\nThat hesitation is exactly how software becomes unmaintainable. Layers of dead functionality pile up, developers spend hours figuring out whether a script is safe to delete, and every new feature has to be built around debris instead of on clean ground. This article walks through how to identify what's actually obsolete, and how to remove it without breaking something that still matters.\n\n## Why not just leave old functionality in place?\n\n\"It's not hurting anything\" is the most common reason obsolete code survives. In practice, it usually is hurting something — just slowly and invisibly.\n\n- **It slows down every future change.** A developer adding a new invoicing rule has to read through three unused variations of the old invoicing logic first, just to be sure none of them are secretly still referenced somewhere.\n- **It increases the attack surface.** An old API connector with hardcoded credentials, still technically live, is a security liability even if nobody uses it — someone still has to patch it, renew its certificate, or explain it in an audit.\n- **It confuses new team members.** A new in-house developer inherits a FileMaker system with four different \"send email\" scripts, three of which are dead ends, and has no way to know which one is safe to extend.\n- **It costs real money.** Unused integrations still consume API call quotas, licensed seats, or server resources every month.\n\nThe goal isn't cosmetic cleanup — it's protecting the team's ability to keep building on the system at all. This is the same reasoning behind our broader guide on [how to keep business software maintainable as it grows](https:\u002F\u002Floggix.com\u002Fen\u002Fblog\u002Fhow-to-keep-business-software-maintainable-as-it-grows): every piece of unused functionality is a small tax on every future change.\n\n## How do you know a feature is actually obsolete?\n\nThis is the step teams skip, and it's the one that causes the most damage. \"Nobody has complained\" is not proof that nobody uses something — it's often proof that the one person who uses it hasn't needed it this quarter.\n\nBefore removing anything, gather real evidence:\n\n1. **Check usage logs, not memory.** If the system is FileMaker-based, look at script usage in the Data Viewer, server-side script logs, or add lightweight logging (a timestamp written to a table each time the script or layout is triggered) for a few weeks before deciding.\n2. **Search for references across the whole system**, not just the obvious place. A field that looks unused on a layout might still be referenced in a calculation, an export script, a webhook payload, or a scheduled server script that runs quarterly.\n3. **Check integrations last, not first.** An API connector that looks idle might just be idle *this week* — some supplier feeds, tax reporting exports, or bank reconciliation jobs only run monthly, quarterly, or at year-end.\n4. **Ask the actual users, by name.** \"Does anyone still use the old commission report?\" in a general team channel gets silence. \"Sarah, do you still pull the Q3 commission report from the old export button?\" gets an answer.\n5. **Look for external dependents.** A shared calculation field, a value list, or a script might feed a dashboard, a partner portal, or a Zapier\u002FMake automation that lives entirely outside the system you're editing.\n\nOnly once you've confirmed near-zero real usage — not assumed it — should something move to the retirement list.\n\n[[IMAGE:left|magnifying glass tracing hidden connections between old software modules]]\n\n## What's the safest process for removing a feature?\n\nTreat retirement as a project with its own steps, not a five-minute delete. A practical sequence that works well in FileMaker and ERP environments alike:\n\n1. **Document what it currently does**, even briefly — one paragraph is enough. This protects you if someone asks six months later why a report changed.\n2. **Disable, don't delete, first.** Comment out the script trigger, hide the button, or turn off the scheduled job — but leave the underlying script, table, or field intact for a defined trial period (2–4 weeks is typical for internal tools; a full billing cycle for anything financial).\n3. **Announce the change before it happens**, not after. A short internal note — \"the old fax cover sheet button will be removed on the 15th; let us know if you still use it\" — turns a silent removal into a visible, low-risk one.\n4. **Monitor for complaints during the trial window.** If nothing breaks and nobody asks, proceed. If something surfaces, you've lost a button click, not a week of debugging a mystery outage.\n5. **Remove the code, not just the interface.** Deleting a button but leaving its script behind (or vice versa) is how systems accumulate the very clutter you're trying to remove. Clean up both.\n6. **Archive before you delete.** Export the old script, module, or table structure into a version-controlled backup or a \"retired\" folder in your FileMaker file before permanent removal, in case a rare edge case resurfaces later.\n7. **Update documentation and onboarding material** so the next developer doesn't go looking for something that's already gone.\n\n## What about functionality tied to integrations or AI tools?\n\nRetiring a button is low risk. Retiring a connector or an automated process is higher risk, because the failure often shows up somewhere else entirely.\n\nA concrete example: a FileMaker system has an old script that pushes daily stock counts to a supplier's now-discontinued ordering portal. The portal has been dead for a year, but the script still runs every night, silently failing and writing an error to a log nobody reads. It looks harmless — until someone finally investigates why nightly server performance dips at 2 a.m., and finds a script retrying a broken connection hundreds of times.\n\nThe same caution applies to AI-assisted features. If a workflow was extended with an AI tool inside FileMaker — for example, an AI step that auto-drafts a customer reply based on order history — retiring the underlying data source or API key without checking dependencies can leave the AI feature calling an endpoint that no longer exists, producing confusing errors instead of a clean failure.\n\nBefore retiring anything integration-related:\n\n- Check whether the endpoint, webhook, or scheduled job is logged as active anywhere in the last 90 days.\n- Confirm with the *other side* of the integration (the supplier, the bank, the partner) whether they still expect data from you.\n- Turn off the schedule before removing the script itself, so you can observe the effect in isolation.\n\n## How do you avoid this pile-up happening again?\n\nRetirement is easier the second time if you build small habits into how features get added in the first place:\n\n- **Tag time-limited features clearly when they're built.** If a promotion calculator is only needed for one campaign, name it accordingly (`Calc_Promo_Summer2024`) so its expiry is obvious later.\n- **Review scripts and integrations yearly**, not only when something breaks. A short annual \"what's still live\" audit — even half a day — catches dead functionality while it's still easy to trace.\n- **Assign an owner to every integration.** Unowned connectors are the ones that outlive their usefulness the longest, because no one feels responsible for questioning them.\n- **Keep a lightweight changelog.** Even a simple internal document listing \"added,\" \"changed,\" and \"retired\" features per quarter makes future cleanup dramatically faster.\n\n## Quick checklist before you remove anything\n\n- [ ] Usage confirmed with logs or data, not memory\n- [ ] All references checked (layouts, scripts, calculations, exports, integrations)\n- [ ] Named users consulted directly, not just asked generally\n- [ ] Feature disabled first, with a defined trial period\n- [ ] Change announced internally before removal\n- [ ] Both interface and underlying code\u002Fscript removed together\n- [ ] Old version archived, not just deleted\n- [ ] Documentation updated\n\n## FAQ\n\n**How long should the trial\u002Fdisable period be before permanent deletion?**\nFor everyday internal tools, 2–4 weeks is usually enough to surface any real dependency. For anything touching finance, payroll, or compliance reporting, wait through at least one full reporting cycle.\n\n**What if we're not sure who built the original feature or why?**\nTreat it as higher risk, not lower. Undocumented, unowned features are exactly the ones most likely to have a hidden dependency. Spend extra time on the reference search before disabling it.\n\n**Should we ever remove something without a trial period?**\nOnly if it's clearly and provably dead — for example, a script referencing a server that no longer exists and returning hard errors every time it runs. Even then, archive it first.\n\n**Does retiring old functionality count as \"maintenance\" or a real project?**\nBoth. It should be scheduled and resourced like a real piece of work, not squeezed in as an afterthought — that's usually why it gets skipped for years at a time.\n\nRetiring old functionality safely is really about visibility: knowing what's actually connected to what before you touch anything. That's often exactly where an outside perspective helps — whether that means an in-house developer working with Loggix to map dependencies in an aging FileMaker system, a business consultancy session to prioritize what's worth cleaning up first, or an API integration review to confirm which external connections are still genuinely in use. If your system has reached the point where nobody's quite sure what's safe to delete anymore, that's usually the right moment to get a second set of eyes on it before it grows any further.","\u003Cp>Every piece of business software eventually collects features nobody uses anymore. A discount calculator built for a promotion that ended three years ago. A &quot;print fax cover sheet&quot; button in a FileMaker system that still runs, technically, even though the fax machine was unplugged in 2019. An old API connector to a supplier you stopped working with, still firing a scheduled script every night. Nobody wants to touch it, because nobody is 100% sure what else it&#39;s quietly attached to.\u003C\u002Fp>\n\u003Cp>That hesitation is exactly how software becomes unmaintainable. Layers of dead functionality pile up, developers spend hours figuring out whether a script is safe to delete, and every new feature has to be built around debris instead of on clean ground. This article walks through how to identify what&#39;s actually obsolete, and how to remove it without breaking something that still matters.\u003C\u002Fp>\n\u003Ch2>Why not just leave old functionality in place?\u003C\u002Fh2>\n\u003Cp>&quot;It&#39;s not hurting anything&quot; is the most common reason obsolete code survives. In practice, it usually is hurting something — just slowly and invisibly.\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>It slows down every future change.\u003C\u002Fstrong> A developer adding a new invoicing rule has to read through three unused variations of the old invoicing logic first, just to be sure none of them are secretly still referenced somewhere.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>It increases the attack surface.\u003C\u002Fstrong> An old API connector with hardcoded credentials, still technically live, is a security liability even if nobody uses it — someone still has to patch it, renew its certificate, or explain it in an audit.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>It confuses new team members.\u003C\u002Fstrong> A new in-house developer inherits a FileMaker system with four different &quot;send email&quot; scripts, three of which are dead ends, and has no way to know which one is safe to extend.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>It costs real money.\u003C\u002Fstrong> Unused integrations still consume API call quotas, licensed seats, or server resources every month.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>The goal isn&#39;t cosmetic cleanup — it&#39;s protecting the team&#39;s ability to keep building on the system at all. This is the same reasoning behind our broader guide on \u003Ca href=\"https:\u002F\u002Floggix.com\u002Fen\u002Fblog\u002Fhow-to-keep-business-software-maintainable-as-it-grows\">how to keep business software maintainable as it grows\u003C\u002Fa>: every piece of unused functionality is a small tax on every future change.\u003C\u002Fp>\n\u003Ch2>How do you know a feature is actually obsolete?\u003C\u002Fh2>\n\u003Cp>This is the step teams skip, and it&#39;s the one that causes the most damage. &quot;Nobody has complained&quot; is not proof that nobody uses something — it&#39;s often proof that the one person who uses it hasn&#39;t needed it this quarter.\u003C\u002Fp>\n\u003Cp>Before removing anything, gather real evidence:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Check usage logs, not memory.\u003C\u002Fstrong> If the system is FileMaker-based, look at script usage in the Data Viewer, server-side script logs, or add lightweight logging (a timestamp written to a table each time the script or layout is triggered) for a few weeks before deciding.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Search for references across the whole system\u003C\u002Fstrong>, not just the obvious place. A field that looks unused on a layout might still be referenced in a calculation, an export script, a webhook payload, or a scheduled server script that runs quarterly.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Check integrations last, not first.\u003C\u002Fstrong> An API connector that looks idle might just be idle \u003Cem>this week\u003C\u002Fem> — some supplier feeds, tax reporting exports, or bank reconciliation jobs only run monthly, quarterly, or at year-end.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Ask the actual users, by name.\u003C\u002Fstrong> &quot;Does anyone still use the old commission report?&quot; in a general team channel gets silence. &quot;Sarah, do you still pull the Q3 commission report from the old export button?&quot; gets an answer.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Look for external dependents.\u003C\u002Fstrong> A shared calculation field, a value list, or a script might feed a dashboard, a partner portal, or a Zapier\u002FMake automation that lives entirely outside the system you&#39;re editing.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Only once you&#39;ve confirmed near-zero real usage — not assumed it — should something move to the retirement list.\u003C\u002Fp>\n\u003Cp>[[IMAGE:left|magnifying glass tracing hidden connections between old software modules]]\u003C\u002Fp>\n\u003Ch2>What&#39;s the safest process for removing a feature?\u003C\u002Fh2>\n\u003Cp>Treat retirement as a project with its own steps, not a five-minute delete. A practical sequence that works well in FileMaker and ERP environments alike:\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Document what it currently does\u003C\u002Fstrong>, even briefly — one paragraph is enough. This protects you if someone asks six months later why a report changed.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Disable, don&#39;t delete, first.\u003C\u002Fstrong> Comment out the script trigger, hide the button, or turn off the scheduled job — but leave the underlying script, table, or field intact for a defined trial period (2–4 weeks is typical for internal tools; a full billing cycle for anything financial).\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Announce the change before it happens\u003C\u002Fstrong>, not after. A short internal note — &quot;the old fax cover sheet button will be removed on the 15th; let us know if you still use it&quot; — turns a silent removal into a visible, low-risk one.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Monitor for complaints during the trial window.\u003C\u002Fstrong> If nothing breaks and nobody asks, proceed. If something surfaces, you&#39;ve lost a button click, not a week of debugging a mystery outage.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Remove the code, not just the interface.\u003C\u002Fstrong> Deleting a button but leaving its script behind (or vice versa) is how systems accumulate the very clutter you&#39;re trying to remove. Clean up both.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Archive before you delete.\u003C\u002Fstrong> Export the old script, module, or table structure into a version-controlled backup or a &quot;retired&quot; folder in your FileMaker file before permanent removal, in case a rare edge case resurfaces later.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Update documentation and onboarding material\u003C\u002Fstrong> so the next developer doesn&#39;t go looking for something that&#39;s already gone.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2>What about functionality tied to integrations or AI tools?\u003C\u002Fh2>\n\u003Cp>Retiring a button is low risk. Retiring a connector or an automated process is higher risk, because the failure often shows up somewhere else entirely.\u003C\u002Fp>\n\u003Cp>A concrete example: a FileMaker system has an old script that pushes daily stock counts to a supplier&#39;s now-discontinued ordering portal. The portal has been dead for a year, but the script still runs every night, silently failing and writing an error to a log nobody reads. It looks harmless — until someone finally investigates why nightly server performance dips at 2 a.m., and finds a script retrying a broken connection hundreds of times.\u003C\u002Fp>\n\u003Cp>The same caution applies to AI-assisted features. If a workflow was extended with an AI tool inside FileMaker — for example, an AI step that auto-drafts a customer reply based on order history — retiring the underlying data source or API key without checking dependencies can leave the AI feature calling an endpoint that no longer exists, producing confusing errors instead of a clean failure.\u003C\u002Fp>\n\u003Cp>Before retiring anything integration-related:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Check whether the endpoint, webhook, or scheduled job is logged as active anywhere in the last 90 days.\u003C\u002Fli>\n\u003Cli>Confirm with the \u003Cem>other side\u003C\u002Fem> of the integration (the supplier, the bank, the partner) whether they still expect data from you.\u003C\u002Fli>\n\u003Cli>Turn off the schedule before removing the script itself, so you can observe the effect in isolation.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>How do you avoid this pile-up happening again?\u003C\u002Fh2>\n\u003Cp>Retirement is easier the second time if you build small habits into how features get added in the first place:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Tag time-limited features clearly when they&#39;re built.\u003C\u002Fstrong> If a promotion calculator is only needed for one campaign, name it accordingly (\u003Ccode>Calc_Promo_Summer2024\u003C\u002Fcode>) so its expiry is obvious later.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Review scripts and integrations yearly\u003C\u002Fstrong>, not only when something breaks. A short annual &quot;what&#39;s still live&quot; audit — even half a day — catches dead functionality while it&#39;s still easy to trace.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Assign an owner to every integration.\u003C\u002Fstrong> Unowned connectors are the ones that outlive their usefulness the longest, because no one feels responsible for questioning them.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Keep a lightweight changelog.\u003C\u002Fstrong> Even a simple internal document listing &quot;added,&quot; &quot;changed,&quot; and &quot;retired&quot; features per quarter makes future cleanup dramatically faster.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>Quick checklist before you remove anything\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Usage confirmed with logs or data, not memory\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> All references checked (layouts, scripts, calculations, exports, integrations)\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Named users consulted directly, not just asked generally\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Feature disabled first, with a defined trial period\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Change announced internally before removal\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Both interface and underlying code\u002Fscript removed together\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Old version archived, not just deleted\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Documentation updated\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>FAQ\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>How long should the trial\u002Fdisable period be before permanent deletion?\u003C\u002Fstrong>\nFor everyday internal tools, 2–4 weeks is usually enough to surface any real dependency. For anything touching finance, payroll, or compliance reporting, wait through at least one full reporting cycle.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>What if we&#39;re not sure who built the original feature or why?\u003C\u002Fstrong>\nTreat it as higher risk, not lower. Undocumented, unowned features are exactly the ones most likely to have a hidden dependency. Spend extra time on the reference search before disabling it.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Should we ever remove something without a trial period?\u003C\u002Fstrong>\nOnly if it&#39;s clearly and provably dead — for example, a script referencing a server that no longer exists and returning hard errors every time it runs. Even then, archive it first.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Does retiring old functionality count as &quot;maintenance&quot; or a real project?\u003C\u002Fstrong>\nBoth. It should be scheduled and resourced like a real piece of work, not squeezed in as an afterthought — that&#39;s usually why it gets skipped for years at a time.\u003C\u002Fp>\n\u003Cp>Retiring old functionality safely is really about visibility: knowing what&#39;s actually connected to what before you touch anything. That&#39;s often exactly where an outside perspective helps — whether that means an in-house developer working with Loggix to map dependencies in an aging FileMaker system, a business consultancy session to prioritize what&#39;s worth cleaning up first, or an API integration review to confirm which external connections are still genuinely in use. If your system has reached the point where nobody&#39;s quite sure what&#39;s safe to delete anymore, that&#39;s usually the right moment to get a second set of eyes on it before it grows any further.\u003C\u002Fp>\n","Jeroen","2026-07-24",1784901675000,[19,20,21,22,23,24],"software maintenance","FileMaker development","technical debt","legacy system cleanup","API integrations","system audits","\u002Fapi\u002Fknowledge\u002Fimage\u002F342\u002F?v=8af52252d8cb",false,"",null,{"title":30,"slug":31},"Modern Software Development","modern-software-development",{"title":33,"slug":34},"How to keep business software maintainable as it grows","how-to-keep-business-software-maintainable-as-it-grows"]