# No-Code SaaS Automation Platform

**Solution Architecture v1.0 · Amazon Web Services · Integration Platform Architecture · 2026-10 · 21 views · 16 architecture decision records**

Almost everyone who works in an office has built one of these without calling it software. A form submission lands, a row appears in a spreadsheet, a message appears in a chat channel. Nobody wrote code and nobody deployed anything, and it has run unattended for two years — until the Tuesday it posts the same message three times, or the month it quietly stops because somebody in IT revoked a token and no human was told, or the Black Friday morning when 900 submissions trickle through over forty minutes because the spreadsheet API started answering `429`. This package is the platform behind that — the Zapier / Make / IFTTT / Power Automate class: an assumed 2,500,000 active workspaces, 8,000 connectors exposing 40,000 actions and triggers, 12,000,000 enabled automations and roughly 1.8 billion step attempts a month; 4,000 trigger events a second accepted at steady state and 12,000 step attempts a second executed, both bursting fourfold; and 2,000,000 polled connections at an average five-minute interval, which is about 6,700 provider polls a second.

The product is trivial to describe and the architecture is not, because the platform owns almost none of the systems it depends on. Its triggers come from products that mostly cannot push. Its effects land in products whose APIs it cannot change, inside quotas it cannot negotiate, using credentials somebody else can revoke at any moment, on behalf of authors who cannot read a stack trace. **Every interesting failure here belongs to somebody else — and every one of them still arrives as a complaint about us.**

The design rests on one rule: **the step attempt, not the run, is the unit of durability — a run is a resumable state machine whose entire state lives in an append-only step ledger outside the worker, and no step may be attempted without a stable effect key.**

The decisions that carry the design:

- **The step attempt is the unit of durability.** A retry, a park for a rate limit, a pause for a dead credential and a resume after a lost worker become one mechanism — moving a run between states — instead of four special cases, and none of them repeats a step that already succeeded (ADR-01).
- **The trigger event log is the platform's own system of record for what happened.** Providers stay authoritative for what is true. Thirty days of retention stops being a storage preference and becomes a promise about how far back a repair can reach (ADR-02).
- **Acceptance and execution fail independently.** The push endpoint authenticates, commits and acknowledges — nothing else — so a 250 ms p99 fits inside every common provider delivery timeout while a run may take minutes, and a total execution outage loses no trigger (ADR-03).
- **Every action declares a replay-safety class.** Idempotent, checkable or unsafe is a stored, versioned property and a hard release gate, because every execution guarantee downstream is derived from it (ADR-04).
- **A retry reuses the effect key; a replay mints a new logical attempt.** The difference between "try again" and "do it again" is structural rather than a parameter, so no code path can deliver one when the author meant the other (ADR-05).
- **An unsafe ambiguous outcome is parked, never retried.** Where the provider offers no key and no read-back, the platform cannot make the step safe, so it names the ambiguity and asks rather than silently choosing a duplicate invoice or a missing one (ADR-06).
- **No runner calls a provider directly.** The quota decision, the credential exchange and the egress identity are one boundary — which is what keeps long-lived credentials out of the execution plane (ADR-07).
- **A rate limit is a park with a release time, not a failure.** `429` is the ordinary case at this scale: the run waits, occupies no worker, and does not spend its retry budget on somebody else's capacity planning (ADR-08).
- **Egress is a published, stable address range, and one tenant's behaviour is everyone's reputation.** Enterprise customers allowlist it, which makes runaway detection part of the same decision rather than a separate feature (ADR-09).
- **Push where available, poll everywhere else, and own the subscription lifecycle.** A subscription that expired unnoticed is this platform's most common invisible failure, and it presents as health (ADR-10).
- **A cursor advances only after durable commit.** Advancing first is the one-line bug that produces a permanent silent gap, and the cursor store is the only store here whose loss cannot be recovered from the two authoritative ones (ADR-11).
- **Credential custody is a separate account.** The prize is not our data, it is access to the customers' other SaaS products — so the blast-radius boundary is an account boundary, and runners hold only single-connection, single-run tokens (ADR-12).
- **Refresh is single-flighted; credential death is terminal.** A thousand concurrent runs on one connection must not produce a thousand refreshes and a rotation race, and a revoked token is never retried as though it were a transient fault (ADR-13).
- **Fair scheduling, with runaway detection in the same decision.** A bulk import is slowed, never permitted to starve, and an automation triggering itself is throttled within a minute (ADR-14).
- **Near-zero idle cost is a constraint, not an optimisation.** Most of twelve million automations fire rarely, which rules out per-automation reserved capacity before the design begins (ADR-15).
- **Every failure carries a classified, author-facing cause and a repair path.** A failure class with no sentence the author can act on is an unfinished feature, which makes the taxonomy a deliverable of the architecture rather than of the UI (ADR-16).

The architecture one-pager (including why the design should still hold up in ten years, and the seven risks that would change it) and the full decision record appear on the landing page of the diagram set, directly below the index of views. The same content is published as [docs/architecture-one-pager.md](docs/architecture-one-pager.md) (~18 min) and [docs/decision-record.md](docs/decision-record.md) (~61 min).

---

## What is here

| Path | Contents |
|---|---|
| `diagrams/index.html` | The landing page: 21 views in seven acts with every format linked, then the **architecture one-pager** and the **decision record** |
| `diagrams/*.html` | One self-contained page per view: the inlined diagram plus the reasoning cards, with copy / PNG / PDF export |
| `diagrams/svg/*.svg` | The same views as SVG with the diagram XML embedded; they re-open fully editable in diagrams.net |
| `diagrams/drawio/*.drawio` | draw.io source |
| `docs/architecture-one-pager.md` | The one-pager as markdown |
| `docs/decision-record.md` | The 16 decision records, the capability-to-technology table and the package glossary as markdown |
| `specs/views.json` | Diagram specifications, the source of truth for every view |
| `specs/manifest.json` | Acts, page titles, subtitles and reasoning cards |
| `specs/adr.json` | The one-pager, the decision records, the capability-to-technology table and the glossary |
| `scripts/render-adr.mjs` | Injects the one-pager and decision record into the index and writes `docs/*.md` |
| `ask.md` | The requirement |

## The twenty-one views

| # | View | What it answers |
|---|---|---|
| 01 | System Context | Who uses it, which third-party classes it reaches, and the two adjacent use cases that own what is out of scope |
| 02 | High-Level Architecture | The whole path in one line, with the step ledger drawn inside execution because it is not a side-effect store |
| 03 | Actors and Their Journeys | Five parties — including the provider API, which is in the cast because it is the only one that can throttle us |
| 04 | Journey — Building the First Automation | The trough is Test, not Publish: the author is asked to prove it works by letting it touch real data |
| 05 | Journey — The Automation That Quietly Stopped | The trough is phase 2: the platform knew, and a colleague told the author |
| 06 | Layered Architecture | Six layers, with the providers drawn as the bottom one to keep the dependency direction honest |
| 07 | Container View | The deployable units, and credential custody in an account of its own |
| 08 | Interface Catalogue | Everything in and out, with the outbound side grouped by whether a retry is safe |
| 09 | Data Flow | A payload becomes authoritative twice; everything after the ledger is derived and droppable |
| 10 | Data Architecture | Five zones by rebuildability, including the small hot one whose loss is unrecoverable |
| 11 | Data Model | Eight entities, and one composite key carrying at-most-once visible effect |
| 12 | Critical Flow — One Run With a Rate Limit | Seventeen messages, drawn with a 429 in the middle because a 429 is the ordinary case |
| 13 | Trigger Ingestion | Push and poll as two mechanisms with two failure taxonomies, not one abstraction |
| 14 | Step Lifecycle by Replay-Safety Class | The same five stages three times; the lanes diverge at the ambiguous outcome and converge nowhere |
| 15 | Deployment | One region across three AZs, and the egress range customers allowlist |
| 16 | Delivery and Connector Release | Two things ship here, and only one of them we wrote |
| 17 | Observability | Six signal families by stage, including the Silence row most platforms of this kind omit |
| 18 | The Automation Health Loop | Detect, classify, hold, notify, repair, observe — a loop because silence has no natural end |
| 19 | Security Zones | Six zones by decreasing exposure, every crossing labelled, custody in its own account |
| 20 | Identity and Access Flow | Grant, store, exchange, use — ending on the 401, which is the branch most identity diagrams omit |
| 21 | Failure Classes and Their Handling | Eight classes, each with detection, hold, resolution and the sentence the author is given |

## Rebuilding

```bash
SK=../../../../.claude/skills/architecture-diagram-portal
node $SK/scripts/build-all.mjs --specs specs/views.json --manifest specs/manifest.json \
     --out diagrams --iconset aws
node scripts/render-adr.mjs
```

Node 20+ and nothing else. No draw.io Desktop, no browser, no network. The build generates the
draw.io sources, fails on any geometry or routing defect, renders the editable and plain SVGs,
writes the HTML pages and the index, and proves every relative link in `diagrams/` resolves;
`render-adr.mjs` then injects the one-pager and the decision record into the index and writes
`docs/*.md`.

At v1.0 the geometry gate reports **0 errors and 0 warnings** across 21 files, the routing gate
**0 errors and 0 warnings** across 159 edges, all 291 nodes resolve to an icon with no weak
matches, and the link check passes on every relative link. Getting the routing gate to zero took
cutting edges and labels rather than tuning them: the context view's six provider boxes became
four capability classes, the layered and zones views gave up labels their layer and zone names
already carried, and the author sign-in edge was dropped from the zones view because view 20 is
entirely about it.

## A note on the numbers

Every rate, latency, ratio, threshold and retention figure in this package is a **stated
assumption**, chosen to be defensible and arguable rather than measured. They are stated precisely
so that a reviewer can disagree with one and follow it to the decision that depends on it.
`ask.md` marks them as assumptions section by section; the decision record's evidence note
restates the operating context in one paragraph.

Four of the seven Core Architecture Questions in `ask.md` are deliberately left open rather than
resolved by the diagrams: where the rate-limit budget lives (Q2), whether the unsafe class's
behaviour is one policy or a per-action product decision (Q3), whether a replay re-reads a retained
payload or re-fetches from the provider (Q5), and what happens to a parked backlog when a
credential is finally reconnected (Q6). Each is named on the view where it bites.
