Skip to content

Conversation

@jason-t-hankins
Copy link
Contributor

@jason-t-hankins jason-t-hankins commented Dec 12, 2025

Created 4 new ADRs to develop actionable guidance on how and when to implement performance enhancements to the Apollo Client/Server within Sharethrift. The following four areas were explored in a sample 'social media' repo, as well as documented in separate ADRs:

  1. UseFragment, HTTP Batch, & Facebook DataLoader
  2. Public Caching for Unauthenticated Queries
  3. Server-Side In-Memory Caching and Permission Handling
  4. Client-Side Only Caching

Click here to test sample repo
Closes #240

Summary by Sourcery

Document GraphQL performance and caching strategies for ShareThrift and enable Mermaid diagram support in the docs site.

Enhancements:

  • Enable Mermaid diagram rendering in the docs application to support sequence and graph diagrams in ADRs.

Documentation:

  • Add ADRs documenting GraphQL optimization patterns, public CDN caching strategies, permission-aware server caching, and client-side Apollo caching guidance.

@jason-t-hankins jason-t-hankins self-assigned this Dec 12, 2025
@jason-t-hankins jason-t-hankins requested review from a team and Copilot December 12, 2025 17:04
@jason-t-hankins jason-t-hankins added the documentation Improvements or additions to documentation label Dec 12, 2025
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Dec 12, 2025

Reviewer's Guide

Adds four architecture decision records (ADRs) documenting Apollo Client/Server performance and caching strategies, and enables Mermaid diagram support in the Docusaurus docs app to render the new sequence/flow diagrams.

Sequence diagram for permission-aware cache lookup in a GraphQL resolver

sequenceDiagram
    participant Client
    participant Resolver
    participant Cache
    participant Database

    Client->>Resolver: Query protectedField
    Resolver->>Resolver: Evaluate user permissions
    alt Unauthorized
        Resolver-->>Client: Error or null
    else Authorized
        Resolver->>Cache: get(cacheKey(userId, role, permissions, query, variables))
        alt Cache hit
            Cache-->>Resolver: Cached result
            Resolver-->>Client: Cached result
        else Cache miss
            Resolver->>Database: Execute query
            Database-->>Resolver: Fresh data
            Resolver->>Cache: set(cacheKey, data, ttl)
            Resolver-->>Client: Fresh data
        end
    end
Loading

Flow diagram for Apollo Client cache policy selection tiers

graph TD
    Start[Query execution] --> Sensitivity{Data sensitivity}

    Sensitivity -->|Highly sensitive<br/>passwords, OTP, cards| NoCache[no-cache]
    Sensitivity -->|Sensitive<br/>balances, private messages| NetworkOnly[network-only]
    Sensitivity -->|User-specific<br/>feeds, dashboards| CacheAndNetwork[cache-and-network]
    Sensitivity -->|Public/static<br/>plans, profiles| CacheFirst[cache-first]

    NoCache --> NoCacheBehavior[Bypass cache entirely]
    NetworkOnly --> NetworkOnlyBehavior[Always fetch from network,<br/>do not reuse cached result]
    CacheAndNetwork --> CacheAndNetworkBehavior[Return cached data immediately,<br/>then refresh in background]
    CacheFirst --> CacheFirstBehavior[Use cache if present,<br/>fallback to network on miss]
Loading

File-Level Changes

Change Details Files
Enable Mermaid diagram rendering in the docs site so ADRs can include sequence and flow diagrams.
  • Configure Docusaurus markdown options to turn on Mermaid support.
  • Register the '@docusaurus/theme-mermaid' theme in the Docusaurus config.
  • Add '@docusaurus/theme-mermaid' as a dependency in the docs app package.json.
  • Update pnpm-lock.yaml to capture the new dependency graph.
apps/docs/docusaurus.config.ts
apps/docs/package.json
pnpm-lock.yaml
Add ADR describing combined use of useFragment, HTTP batching, and DataLoader for end-to-end GraphQL performance optimization.
  • Document context, options, and decision to adopt all three patterns together (DataLoader, HTTP batching, useFragment + @nonreactive).
  • Capture technical details on DataLoader batching, HTTP batch link configuration, fragment colocation, and APQ compatibility trade-offs.
  • Include Mermaid-based sequence/flow diagrams for DataLoader, HTTP batching, and useFragment re-render behavior.
  • Reference the external Social-Feed demo repo and specific demo components used for validation.
apps/docs/docs/decisions/0024-usefragment-vs-httpbatch-dataloader.md
Add ADR defining public GraphQL caching strategy using separate public and authenticated endpoints and APQ.
  • Describe context and risks of caching GraphQL responses, especially JWT and POST semantics.
  • Evaluate options and choose separate public and authenticated endpoints as the recommended approach.
  • Detail technical setup for APQ with GET, CDN cache-control headers, and query classification (public vs private).
  • Provide Mermaid sequence diagram comparing public (CDN-cached) vs authenticated (non-cached) flows and link to demo pages in the Social-Feed repo.
apps/docs/docs/decisions/0025-public-graphql-caching.md
Add ADR for permission-aware server-side in-memory caching for GraphQL resolvers.
  • Document the need to prevent permission leakage while still benefiting from server-side caching.
  • Select permission-aware cache keys as the recommended approach and outline cache key composition (query, variables, user, role, permissions).
  • Describe TTL, LRU-based eviction, and hybrid invalidation (TTL + mutation-based) strategies.
  • Include Mermaid diagrams for cache isolation and permission-aware resolver flow and link to the PermissionCache demo.
apps/docs/docs/decisions/0026-permission-aware-caching.md
Add ADR for client-side caching strategy in Apollo Client, including security- and UX-driven fetch policy guidance.
  • Summarize cache policy options (cache-first, cache-and-network, network-only, no-cache) and when to use each.
  • Define a tiered strategy based on data sensitivity (public, user-specific, sensitive, highly sensitive).
  • Describe field-level security via type/field policies, optimistic updates, cache invalidation approaches, and debugging/monitoring practices.
  • Include Mermaid diagrams for optimistic update flow and cache policy decision flow and link to the ClientCache demo.
apps/docs/docs/decisions/0027-client-side-caching.md

Assessment against linked issues

Issue Objective Addressed Explanation
#240 Create architecture decision records (ADRs) that document guidance for Apollo Client/Server enhancement areas including useFragment vs HTTP batching/DataLoader, public caching strategies, server-side caching, and client-side caching.
#240 Provide or reference a dedicated sample application/repository that demonstrates complex or contrived GraphQL scenarios relevant to the explored Apollo Client/Server enhancements.

Possibly linked issues

  • Explore Apollo Client/Server Enhancement Options and Guidance #240: The PR implements the issue’s request by adding ADRs and a demo repo covering the specified Apollo optimization areas.
  • #: PR’s 0027 Client-Side Caching ADR and demo repo fulfill the issue’s requested guidance and PoC.
  • #N/A: The PR’s 0026 Permission-Aware Caching ADR directly fulfills the requested guidance on in-memory caching and permissions.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • In the ADR markdown files there are a few copy/paste artifacts that make them harder to read (e.g., 0026 has both a structured ## Consequences list and a separate ### Consequences bullet section, and 0024 has ## More Information duplicated); consider consolidating these sections so each ADR has a single, clearly structured consequences/info block.
  • The PermissionAwareCache example in 0026 currently omits some implementation details (e.g., this.cache is never initialized and matchesPattern is referenced but not defined); it would be helpful to either stub these explicitly or annotate the snippet as pseudo-code to avoid confusion for readers trying to copy the pattern.
  • In 0027, the reference to "See ADR 0001 for re-render optimization details" appears inconsistent with the ADR numbering introduced in this PR (the useFragment guidance lives in 0024); updating cross-references to the correct ADR IDs will make the guidance easier to navigate.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the ADR markdown files there are a few copy/paste artifacts that make them harder to read (e.g., 0026 has both a structured `## Consequences` list and a separate `### Consequences` bullet section, and 0024 has `## More Information` duplicated); consider consolidating these sections so each ADR has a single, clearly structured consequences/info block.
- The `PermissionAwareCache` example in 0026 currently omits some implementation details (e.g., `this.cache` is never initialized and `matchesPattern` is referenced but not defined); it would be helpful to either stub these explicitly or annotate the snippet as pseudo-code to avoid confusion for readers trying to copy the pattern.
- In 0027, the reference to "See ADR 0001 for re-render optimization details" appears inconsistent with the ADR numbering introduced in this PR (the useFragment guidance lives in 0024); updating cross-references to the correct ADR IDs will make the guidance easier to navigate.

## Individual Comments

### Comment 1
<location> `apps/docs/docs/decisions/0025-public-graphql-caching.md:284` </location>
<code_context>
+
+| Query | Public? | Reason |
+|-------|---------|--------|
+| `userById()` | ✅ Yes | Should be able to see users pages, specifics may be blocked |
+| `accountPlans()` | ✅ Yes | Shown to unauthenticated users during signup |
+| `currentUser()` | ❌ No | requires authentication and could cause errors |
</code_context>

<issue_to_address>
**issue (typo):** Fix possessive form in "users pages"

Change to the possessive form, e.g. "users' pages" or "user pages," for correct grammar.

```suggestion
| `userById()` | ✅ Yes | Should be able to see users' pages, specifics may be blocked |
```
</issue_to_address>

### Comment 2
<location> `apps/docs/docs/decisions/0024-usefragment-vs-httpbatch-dataloader.md:128` </location>
<code_context>
+   - **Research**: Cloudflare study shows 35-50% improvement in multi-query scenarios
+
+   **Important Limitation:**
+   - HTTP Batching does not provide improvement on static web pages or sites with minimal queries.
+   - Large batchIntervals and small batchIntervals will have linear effects on the performance depending on the number of simultaneous requests. (If you have a large batch and a small number of requests, you may end up waiting longer than necessary)
+
+### Implementation for ShareThrift
</code_context>

<issue_to_address>
**suggestion (typo):** Fix "batchIntervals" spacing and consider simplifying wording

In "Large batchIntervals and small batchIntervals", this should likely be "batch intervals" (with a space). You could also avoid repeating the term by rephrasing, e.g., "Large and small batch intervals will have linear effects..."

```suggestion
   - Large and small batch intervals will have linear effects on performance depending on the number of simultaneous requests. (If you have a large batch and a small number of requests, you may end up waiting longer than necessary)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces comprehensive guidance for Apollo Client/Server performance optimization in ShareThrift through four new Architecture Decision Records (ADRs). The documentation is based on practical experimentation in a separate "Social-Feed" demo repository and provides actionable patterns for GraphQL optimization at multiple layers: client-side rendering, network transport, server-side caching, and public CDN caching.

Key Changes

  • ADR 0024 establishes guidance on three complementary optimization patterns: useFragment for re-render reduction, HTTP batching for network consolidation, and DataLoader for N+1 query elimination
  • ADR 0025 defines a dual-endpoint architecture pattern for enabling CDN caching of public GraphQL content while maintaining security for authenticated requests
  • ADR 0026 documents a permission-aware caching strategy that safely caches server-side data while preventing unauthorized access across different user roles
  • ADR 0027 provides a tiered client-side caching strategy based on data sensitivity, from public static content to highly sensitive credentials

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 18 comments.

File Description
apps/docs/docs/decisions/0024-usefragment-vs-httpbatch-dataloader.md Documents GraphQL optimization patterns (useFragment, HTTP batching, DataLoader) with implementation guidance, trade-offs, and validation testing results
apps/docs/docs/decisions/0025-public-graphql-caching.md Defines separate endpoint architecture for public vs authenticated GraphQL requests with CDN caching support using APQ and GET requests
apps/docs/docs/decisions/0026-permission-aware-caching.md Establishes permission-aware cache key structure to safely cache server-side GraphQL responses while preventing data leakage between user roles
apps/docs/docs/decisions/0027-client-side-caching.md Specifies tiered Apollo Client cache policies based on data sensitivity (cache-first, cache-and-network, network-only, no-cache) with field-level masking

Copy link
Contributor

@jasonmorais jasonmorais left a comment

Choose a reason for hiding this comment

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

Didnt fully granulary go through the last file but i think theres enough to do for now:

  1. We dont want actual code examples in here. Where there is code try to explain with english, or try to use mermaid diagrams. This should be a high level document/documents. An example is in the pr i linked in one of the comments for a mermaid diagram. I would also verify all common sections are included, besides the one i mentioned, along with keeping that consistency

  2. Please resolve the copilot and sourcery comments remaining.

@jason-t-hankins jason-t-hankins marked this pull request as draft December 17, 2025 14:16
@jason-t-hankins jason-t-hankins marked this pull request as ready for review December 17, 2025 17:57
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `apps/docs/docs/decisions/0024-usefragment-vs-httpbatch-dataloader.md:91` </location>
<code_context>
+
+### Automatic Persisted Queries (APQ) Compatibility
+
+APQ sends query hashes instead of full query strings to reduce request size. DataLoader, HTTP Batching (POST), useFragment are compatible with APQ. However, HTTP Batching (GET) is not compatible.Must choose between HTTP Batching (POST) OR CDN Caching (GET) - cannot use both simultaneously. **GET mode** (`useGETForHashedQueries: true`)
+
+### Fragment Colocation vs Container Pattern
</code_context>

<issue_to_address>
**suggestion (typo):** Fix minor grammar in the APQ compatibility sentence.

Please fix the missing space and tweak the phrasing, e.g.: `DataLoader, HTTP Batching (POST), and useFragment are compatible with APQ. However, HTTP Batching (GET) is not compatible. You must choose between HTTP Batching (POST) OR CDN Caching (GET) – you cannot use both simultaneously.`

```suggestion
APQ sends query hashes instead of full query strings to reduce request size. DataLoader, HTTP Batching (POST), and useFragment are compatible with APQ. However, HTTP Batching (GET) is not compatible. You must choose between HTTP Batching (POST) OR CDN Caching (GET) – you cannot use both simultaneously. **GET mode** (`useGETForHashedQueries: true`)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

@jasonmorais jasonmorais 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 comment, after that will forward to nick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explore Apollo Client/Server Enhancement Options and Guidance

3 participants