Plan a script for long-term maintainability
Documentation, comments, and handover habits for Northwind's enduring automations.
Published Oct 19, 2025
A script that runs on a trigger keeps working long after the person who wrote it has moved on to other things. Months later someone needs to change it, debug it, or simply confirm it still does what they think — and by then the original context is gone.
Maintainability is not about clever code; it is about leaving enough of a trail that the next person (often a future version of you) can understand the script without reverse-engineering it. The habits below cost a few minutes up front and save hours later.
Six habits
These six practices, applied consistently, are what separate a script that ages well from one that becomes untouchable.
- One README per script. Put a comment block at the top of
Code.gsstating what the script does, who owns it, and when it runs. - Name functions for intent.
pullStripeChargesDaily()tells the reader what and when;runIt()tells them nothing. - Pin dependencies. Reference a fixed library version in
appsscript.json, never “latest” — an upstream change should never silently alter your script’s behaviour. - Document properties. Every Script Property is invisible until someone opens the settings panel; comment in code what each one means.
- Log who set up triggers. Create triggers from a named
setupTriggersfunction so the act is traceable in version history, not a mystery click. - Use clasp + Git. Real version control — branches, diffs, commit messages — beats Apps Script’s flat revision history for anything serious.
The README block
The single highest-value habit is the header comment. It is the first thing a new maintainer sees, and it answers the questions they will ask first: what is this, who owns it, and what does it depend on.
/**
* Northwind Stripe sync
* Owner: [email protected]
* Runs: hourly via time trigger.
* Source: github.com/northwind/scripts/stripe-sync
*
* Properties:
* STRIPE_KEY: API key (rotate annually)
* LAST_CHARGE_ID: cursor, do not edit
*/
Each line earns its place. Without an owner, no one knows who to ask. Without
the source line, no one knows where the canonical code lives. Without the
property notes, the next person edits LAST_CHARGE_ID by hand and breaks the
cursor.
What rots fast
Some parts of a script decay faster than others. Knowing which lets you watch them — or design them out before they become a problem.
| Decays | Why it rots | Fix it with |
|---|---|---|
| ”Temporary” hardcoded values | The fix outlives the deadline | A documented Script Property |
| Triggers owned by people who left | Triggers belong to a Google account | A traceable setupTriggers function |
| Unnamed dependency Sheets | The link is implicit and easy to break | Naming every Sheet ID in the README |
| ”Latest” library versions | Upstream changes arrive unannounced | A pinned version number |
The pattern is the same each time: anything implicit eventually becomes invisible. A value buried in code, a trigger tied to a personal account, a dependency that is never named — each works fine until someone needs to find it, and by then there is nothing to find.
Common mistakes
- Leaving the script with no owner. When something breaks, the first question is “whose is this?” — make sure the file answers it.
- Hardcoding IDs and keys instead of using documented properties. The script becomes impossible to move or hand over safely.
- Installing triggers by clicking through the UI. They vanish from version history and break when that account loses access.
- Relying on Apps Script’s revision history as version control. It has no branches, no diffs, and no commit messages — use clasp and Git instead.
- Writing comments that describe what the code does, not why. The “what” is visible in the code; the “why” is the part that gets lost.