Skip to content

Conversation

evenkkl
Copy link
Member

@evenkkl evenkkl commented Sep 28, 2026

What this does

Documentation for #3: short architecture decision records, so peer reviewers and examiners can follow why we built Crate the way we did.

It is written from what the repo already says: schema.graphql, docs/data-model.md and the architecture rules in AGENTS.md. It was not copied from archive/scaffold-prototype.

What was done

docs/architecture.md has six decisions. Each one has context, options considered, the decision and its consequences:

  1. PostgreSQL + GraphQL Yoga, not MongoDB, Neo4j or a BaaS
  2. Keyset (cursor) pagination, not OFFSET
  3. Sorting and filtering in SQL
  4. Per-request DataLoaders against N+1
  5. Simulated users instead of login
  6. Plain CSS, Apollo Client cache and URL as search state

What was tested

Markdown only, so the relevant gate is formatting:

prettier --check docs/architecture.md   ✅

pnpm lint / typecheck / test do not apply, because the PR adds no code.

Notes

  • AGENTS.md says the simulated user id is sent "with every mutation". But myCrate, myReview and isInCrate are queries, so the id has to go with those requests too. Decision 5 says "each request". Worth agreeing on before M2.
  • Most of these decisions are implemented in M2 and M3, so the doc describes the plan rather than existing code.

Closes

Closes #3.

Add docs/architecture.md with six short decision records so peer
reviewers and examiners can follow our reasoning. Each one covers
context, options considered, the decision and its consequences:

- PostgreSQL + GraphQL Yoga over MongoDB, Neo4j or a BaaS
- keyset (cursor) pagination instead of OFFSET
- sorting and filtering in SQL
- per-request DataLoaders against N+1
- simulated users instead of login
- plain CSS, Apollo Client cache and URL as search state

Closes #3
@evenkkl evenkkl added this to the M1 — Utkast og arkitektur milestone Sep 28, 2026
@evenkkl evenkkl requested a review from a team as a code owner September 28, 2026 18:26
@evenkkl evenkkl linked an issue Sep 28, 2026 that may be closed by this pull request
Copy link
Member

@robertky robertky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small wording suggestion for decision 3: consider writing “parameterised SQL queries” instead of “one parameterised query”. Search results, totalCount, and genre facets may naturally require separate parameterised queries, without changing the decision to perform filtering and sorting in the database.
It would also be good to rebase the branch onto the current main afterwards, so the PR receives a CI run against the latest setup.

Reword three decisions after review: - keyset pagination: "paging stays efficient on later pages" instead   of "every page is equally fast" - sorting and filtering: parameterised SQL queries, since results,   totalCount and facets may be separate queries - Apollo cache: returning the album updates its cached data, but lists   such as myCrate and reviews may still need a cache update or refetch Refs: #3
Copy link
Member

@rachelks rachelks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good after the small wording changes!

@rachelks rachelks merged commit cd18740 into main Oct 1, 2026
2 checks passed
erikhfj added a commit that referenced this pull request Oct 1, 2026
…start

Two bugs, both reported by rachelks after #36 merged and the deploy went
red.

1. `systemctl list-unit-files | grep -q '^crate-api.service'` took the
   else branch even when the unit was installed. `grep -q` exits at the
   first match and closes the pipe, `systemctl` gets SIGPIPE and dies,
   and with `pipefail` the pipeline reports failure so the `if` falls
   through to "not installed yet, skipping". Whether it matched or not
   depended on how much output `systemctl` had flushed before grep
   closed, which is why it was intermittent. The log said:

       Failed to print table: Broken pipe
       crate-api.service not installed yet (arrives in M2). Skipping.

   Replaced with `[ -f /etc/systemd/system/crate-api.service ]`. No
   pipe, no SIGPIPE, no pipefail interaction.

2. `sudo systemctl restart crate-api` fails because the self-hosted
   runner has no TTY and no passwordless rule:

       sudo: A terminal is required to authenticate

   Needs a NOPASSWD rule scoped to exactly these commands. That is a
   change on the VM, not in this file, so it is called out in the step
   comment and in the PR.

Also gated the restart on `server/` actually being in the repository.
The unit on the VM still points at prototype code from 23 Sep, and
`server/` does not exist on main until M2. Restarting unconditionally
would bring that stale process back. Now it skips with a stated reason
while M1 is the current state, and fails loudly if `server/` exists but
was never built.

Reported by rachelks.

Co-Authored-By: opencode <noreply@opencode.ai>
@rachelks rachelks deleted the docs/3-architecture-decisions branch October 15, 2026 08:30
Sign in to join this conversation on GitHub.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Architecture decision records
3 participants