Notion and CodeWords: keeping a workspace from rotting
Pages nobody has opened in a year, databases that became systems of record, the block structure that makes the API awkward, and what to automate when documentation is the product.
On this page
- What we'll cover
- How a workspace rots
- Blocks, which make the API awkward
- What the Notion API reaches
- Connecting it to CodeWords
- Seven automations worth building
- When a Notion database should not be the system of record
- Making a database an automation can work with
- Building it so it survives
- Limits worth knowing about
- What to build first
- Frequently asked questions
- Related reading
Notion workspaces rot in a specific way. Nobody deletes anything, so the wrong answer from eighteen months ago sits alongside the right one from last week with no visible difference between them. Search returns both. New people find whichever ranks higher.
That is the problem worth automating, and it is more valuable than anything involving creating pages. A workspace where people trust what they find is worth considerably more than one with more in it.
What we'll cover
- How a workspace rots
- Blocks, which make the API awkward
- What the Notion API reaches
- Connecting it to CodeWords
- Seven automations worth building
- When a Notion database should not be the system of record
- Making a database an automation can work with
- Building it so it survives
- Limits worth knowing about
- What to build first
- Frequently asked questions
How a workspace rots
Nothing is ever wrong, only old. A page describing a process that changed looks exactly as authoritative as one describing the current process.
Duplicates accumulate. Somebody could not find the existing page, so they wrote a new one. Now there are two, slightly different.
Ownership evaporates. The person who wrote it left, and nobody inherited responsibility for whether it is still true.
Nesting hides things. A page four levels deep is effectively invisible, which is why somebody wrote the duplicate.
Databases outgrow their purpose. A tracker becomes the place four people check daily, without any of the constraints a system of record needs.
Automation addresses the first four by making age, ownership, and duplication visible. The fifth is covered separately, because the answer there is usually not automation.
Blocks, which make the API awkward
Worth understanding before designing anything, because it shapes what is practical.
Page content is a tree of blocks, not a document. A paragraph, a heading, a toggle, and a table are each blocks, and blocks can contain other blocks.
Reading a page means walking that tree. Fetching a page returns its properties, and the content requires listing its children, recursively, which is several requests for a substantial page.
Rich text is structured. A sentence with bold and a link is an array of segments with annotations rather than a string, so anything reading or writing text handles that structure.
Writing is append-oriented. Adding blocks is straightforward; editing existing content in place is more involved, and reconstructing a page wholesale is often simpler than surgically modifying it.
Databases are different from pages. A database row is a page with properties, and querying a database is a different operation from reading page content. Most useful automation works with database properties rather than page bodies, because properties are structured and bodies are not.
What the Notion API reaches
Databases can be queried with filters and sorts, and their schema read.
Pages can be created, read, and updated, including their properties.
Blocks can be listed, appended, updated, and deleted, which is how page content is manipulated.
Users can be listed, which matters for anything about ownership.
Search covers pages and databases the integration has access to, with the important caveat that access is granted per page rather than workspace-wide.
Comments can be read and created, which is a good place for automated observations, since they are visible without altering the page.
Connecting it to CodeWords
CodeWords connects to more than 3,000 integrations, and the connection is made once and reused.
- Open CodeWords and start a new automation.
- Describe what should happen in plain language to Cody, the automation builder: which database or pages, and what should happen.
- Authorize the connection, then share the relevant pages with the integration inside Notion, since access is granted per page and an integration sees nothing until you do.
- Describe the exceptions: a page that has been deleted, a property that does not exist, a relation pointing at something removed.
- Test against a duplicated database before pointing anything at the real one.
You describe the outcome; Cody builds it, connects it, and deploys it. The free plan covers light use, with Pro at $39 per month and Business at $100 per month as usage grows; details are on the pricing page.
Seven automations worth building
Staleness reporting. Pages not edited within a threshold, with their owner named, reported as a review list. The single highest-value automation here, because it converts an invisible problem into a short weekly task.
Ownership gaps. Pages with no owner property, or an owner who has left, surfaced for reassignment.
Duplicate detection. Pages with very similar titles or content, reported so somebody can merge or delete. This is what stops the workspace forking.
Intake from elsewhere. Create database rows from forms, tickets, or CRM events, with properties populated, so nobody retypes.
Digest of what changed. What was edited this week, by whom, in the areas people care about, delivered to a channel. Notion's own notifications are per page and do not aggregate.
Reconciliation for tracker databases. Where a database duplicates something another system owns, compare and report the differences.
Link rot checking. External links in pages that no longer resolve, reported for fixing. Documentation quietly fills with dead links and nobody checks.
When a Notion database should not be the system of record
Worth saying plainly, because Notion makes it very easy to end up here.
No constraints. Nothing prevents a required property being empty, a date being nonsense, or a status being a value that no longer exists in the workflow.
No referential integrity. A relation to a page that has been deleted leaves a dangling reference.
Performance degrades with size. A database with tens of thousands of rows is slow to query and slow to use.
Concurrent editing is for documents, not transactions. Two people editing rows simultaneously is fine; two processes incrementing a number is not.
Access control is per page. Fine-grained permissions on a row are not available, so a database everyone can see is one everyone can edit.
Where the data is genuinely operational — anything with money, obligations, or customer commitments — those absences matter. Automation can compensate by checking and reporting, and it is compensating rather than solving. Saying so is more useful than quietly building a scaffold that keeps a fragile arrangement standing for another two years.
Making a database an automation can work with
Most of the difficulty in Notion automation comes from database design, and a few choices decide whether it is straightforward or painful.
Use select rather than text for anything with fixed values. A status field typed as text accumulates "In progress", "in-progress", and "In Progress", and no automation can reason about that.
Give every row a stable identifier. A title can be edited and a Notion page identifier is not meaningful to your other systems. A dedicated property holding the source system's key makes everything downstream possible.
Prefer relations to typed names. A relation to a page is durable; a person's name typed into a text field is not, and reconciliation against it is guesswork.
Add a property for the automation's own state — when it last processed the row, and what it did. Without it you cannot tell a row that was skipped from one that was never seen.
Keep property names stable and boring. They are effectively an interface, and people rename them casually because nothing warns them anything depends on it.
Decide what an empty property means per property, since Notion allows every field to be blank and an automation will meet all of them eventually.
Building it so it survives
Make it safe to run twice. Check for an existing page by a stable identifier stored in a property before creating, since retried webhooks produce duplicates otherwise.
Reference properties by name carefully. Renaming a property breaks automations matching on it, and people rename properties casually.
Handle pagination. Database queries and block listings are both paginated, and an automation reading the first page silently under-reports.
Prefer comments over edits for observations. An automated note added as a comment is visible and does not alter the page, which matters when the page is somebody's work.
Report the outcome. Pages checked, flagged, and created, with anything skipped.
Limits worth knowing about
Rate limits are modest compared with most APIs, roughly a few requests per second, so anything walking a large workspace needs pacing and patience.
Access is per page. An integration sees only what has been shared with it, which is a sensible security model and the most common reason an automation finds nothing.
Block reading is recursive, so a large page costs many requests, which interacts badly with the rate limit.
Property types are strict. Writing a value of the wrong shape for a property type fails, and the shapes differ per type in ways worth checking against an existing row.
Deleted pages are archived rather than removed, so an automation may find pages that appear gone, and should check the archived flag.
What to build first
Staleness reporting: pages not edited within a threshold, with their owner, as a weekly review list. Read-only, quick, and it makes visible the thing that actually degrades a workspace. Most teams discover that a meaningful share of their documentation has not been touched since the person who wrote it left.
Two habits make the difference. Set the threshold by content type rather than uniformly, since a process document going untouched for a year may be fine and a pricing page may not. And send the list to owners rather than to a general channel, because a list addressed to nobody gets read by nobody.
Frequently asked questions
Why does my automation not see any pages?
Because Notion grants integration access per page. Sharing the parent page or database with the integration inside Notion is a manual step, and it is the reason nearly every first Notion automation returns nothing.
Can an automation edit existing page content?
It can, and appending is far simpler than modifying in place because content is a block tree rather than text. For observations, a comment is usually better than an edit, since it is visible without changing somebody's page.
Should we use a Notion database as a system of record?
For lightweight internal tracking, it works well. For anything operational — money, obligations, customer commitments — the absence of constraints and referential integrity matters, and automation checking for problems is compensating rather than fixing. It is worth being honest about which situation you are in.
How do I avoid hitting the rate limit?
Pace requests, query databases with filters rather than reading everything, and avoid walking block trees where database properties would answer the question. Notion's limits are lower than most APIs, which shapes what is practical more than anything else here.
How do I detect duplicate pages?
Compare titles and content across the workspace and report similar pairs for a person to judge. Merging automatically is a poor idea, since two similar pages are sometimes deliberately different, and the judgement is quick for a human and unreliable for a machine.
Can it sync a Notion database with another system?
Yes, and decide which one owns each field first. Notion's editability means somebody will change a value that another system considers authoritative, and bidirectional sync without a clear owner produces fields that flip.
What is the most useful thing to report weekly?
Stale pages with owners, and pages whose owner has left. Those two lists together account for most of the documentation people eventually stop trusting, and both are trivially computable and invisible otherwise.
What is the most common Notion database design mistake?
Free text where a select should be. Status, category, and priority as text fields accumulate variants that differ only in capitalisation or spacing, and no automation can group them reliably — nor can Notion's own views.
How should an automation record what it has already done?
In a property on the row: when it was processed and what happened. It makes the automation idempotent, and it lets a person tell the difference between a row that was deliberately skipped and one the automation never saw.