Skip to content

Commit 25351b2

Browse files
committed
updates
1 parent 9384794 commit 25351b2

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

docs/adr/0047-remove-graphql-from-fxa-settings.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Remove GraphQL from fxa-settings
22

33
- Status: proposed
4-
- Deciders: Vijay Budhram, Lauren Zugai, Dan Schomburg, Barry Chen, Valerie Pomerleau
4+
- Deciders: Vijay Budhram, Lauren Zugai, Dan Schomburg, Barry Chen, Valerie Pomerleau, Amri Toufali, Reino Muhl
55
- Date: 2026-01-14
66

77
This ADR looks at fully removing GraphQL and Apollo from fxa-settings, building on [ADR-0044](0044-use-rest-over-gql-when-convenient.md) which established a preference for auth-client over GraphQL.
@@ -19,6 +19,10 @@ This ADR evaluates whether to complete that migration by fully removing GraphQL
1919
## Decision Drivers
2020

2121
- **Operational complexity**: Running and maintaining `fxa-graphql-api` as a separate service
22+
- **Infrastructure overhead**: Currently requires 4 additional Fastly sites (prod/stage for GraphQL and internal auth endpoints), generating monitoring noise despite lower traffic volumes
23+
- **Security surface area**: GraphQL exposes a flexible query language that requires allowlists to restrict operations; removing it eliminates this attack vector and the need for allowlist generation/maintenance
24+
- **Rate limiting**: Setting up firewall-level rate limits for GraphQL is a pain since everything goes through one endpoint
25+
- **Error monitoring**: With GraphQL, we can't easily get error rates or request counts per operation in Sentry or our dashboards
2226
- **Developer experience**: Cognitive load of maintaining two data-fetching paradigms
2327
- **Testing complexity**: Apollo mocking vs direct auth-client mocking
2428
- **State management**: Apollo Cache reactivity vs localStorage with `useSyncExternalStore`
@@ -33,26 +37,34 @@ This ADR evaluates whether to complete that migration by fully removing GraphQL
3337

3438
## Decision Outcome
3539

36-
TBD
40+
**Chosen option: Option B** - Fully remove GraphQL from fxa-settings.
41+
42+
- We're maintaining 4 extra Fastly sites, generating allowlists, and running a whole separate service for GraphQL. That's a lot of overhead for what we're getting out of it.
43+
- Having two ways to fetch data (GraphQL and auth-client) is confusing.
44+
- We never really used Apollo Cache the way it was meant to be used anyway, so we're not losing much there.
3745

3846
### Positive Consequences
3947

4048
- **Reduced operational complexity**: No need to run/maintain `fxa-graphql-api` for settings
49+
- **Infrastructure simplification**: Eliminates 4 Fastly sites (prod/stage for GraphQL and internal auth endpoints) that currently generate monitoring noise and operational overhead despite lower traffic volumes
50+
- **Reduced attack surface**: Removes GraphQL query language exposure and eliminates the need for query allowlist generation/maintenance; attackers can no longer craft arbitrary GraphQL queries
4151
- **Simpler testing**: Direct auth-client mocking instead of Apollo MockedProvider
4252
- **Clearer data flow**: Components → auth-client → auth-server (no GraphQL proxy layer)
53+
- **Cleaner architecture**: We stop proxying calls through graphql-api just to reach auth-server
4354
- **Native React state management**: Uses React 18's `useSyncExternalStore` for localStorage reactivity instead of Apollo Cache
4455
- **Smaller bundle size**: Removing `@apollo/client` dependency (~100KB+ gzipped)
4556
- **Faster development**: No need to create GraphQL resolvers, mutations, and types for new features
4657
- **Better error handling**: Direct REST errors vs GraphQL error wrapping
47-
- **Positioned for NextJS**: Clean slate for re-evaluating data fetching when migrating to NextJS
58+
- **Better monitoring**: Sentry and our dashboards work better with REST endpoints since we get clear per-endpoint error rates and request counts
59+
- **Positioned for NextJS**: NextJS has its own opinions about data fetching (Server Components, server actions, etc.) that don't mesh well with Apollo's client-side cache. If we migrate to NextJS with Apollo still in place, we'd have to rip it out then anyway. Better to do it now when we can take our time, rather than during a framework migration when we're already juggling a lot.
4860

4961
### Negative Consequences
5062

5163
- **Migration effort**: Requires completing migration of remaining GraphQL usages
52-
- **Custom state synchronization**: Must use `useSyncExternalStore` with custom events for localStorage reactivity (replacing Apollo Cache's built-in reactivity)
53-
- **Lost GQL benefits**: Lose declarative data requirements, GraphQL playground, and schema documentation
64+
- **Custom state synchronization**: Must use `useSyncExternalStore` with custom events for localStorage reactivity (replacing Apollo Cache's built-in reactivity). Note: TanStack Query could help here if we want caching and automatic refetching, but it's not required for our current needs.
65+
- **Lost GQL benefits**: Lose declarative data requirements, GraphQL playground, and schema documentation (though in practice, nobody on the team actively uses the playground)
5466
- **Requires server changes**: Auth-server endpoints must return all needed data (consolidated endpoints)
55-
- **Testing patterns change**: Teams must learn new mocking patterns
67+
- **Testing patterns change**: Teams must learn new mocking patterns (though we already have auth-client mocking patterns in place from existing code)
5668

5769
## Pros and Cons of the Options
5870

@@ -71,13 +83,17 @@ This is the status quo from ADR-0044 - prefer auth-client but keep GraphQL where
7183

7284
### Option B: Fully remove GraphQL from fxa-settings
7385

74-
Complete the migration to auth-client with localStorage for persistence and `useSyncExternalStore` for reactive state management. This pattern provides React component reactivity to localStorage changes without requiring a separate state management library.
86+
Complete the migration to auth-client with localStorage for persistence and `useSyncExternalStore` for reactive state management.
87+
88+
**Why `useSyncExternalStore`?** One thing Apollo gives us is automatic re-renders when cached data changes. When we remove Apollo, we lose that. We still need components to update when account data changes (e.g., user updates their display name and it should show up everywhere). React 18's `useSyncExternalStore` lets us do this with localStorage: components subscribe to changes, and when we update the stored account data, all subscribed components re-render. It's built into React, so no extra libraries needed.
7589

7690
- Good, because single data-fetching pattern reduces cognitive load
7791
- Good, because testing is simpler with direct auth-client mocks
7892
- Good, because eliminates GraphQL service dependency for settings
7993
- Good, because consolidated `/account` endpoint reduces API calls (9 → 3)
80-
- Good, because positions codebase well for NextJS migration
94+
- Good, because positions codebase well for NextJS migration (NextJS prefers server-side data fetching which doesn't play nice with Apollo's client-side cache; removing it now means one less thing to deal with during migration)
95+
- Good, because reduces attack surface by eliminating GraphQL query language exposure and allowlist requirements
96+
- Good, because eliminates 4 Fastly sites and associated operational/monitoring overhead
8197
- Good, because smaller bundle size without Apollo client
8298
- Bad, because requires completing migration work
8399
- Bad, because replaces Apollo Cache reactivity with custom `useSyncExternalStore` + localStorage pattern
@@ -89,7 +105,7 @@ Complete the migration to auth-client with localStorage for persistence and `use
89105
Refactor to use libs directly in graphql-api (deprecate auth-client), as described in FXA-8633.
90106

91107
- Good, because eliminates mixed paradigm by going fully GraphQL
92-
- Good, because achieves end-to-end type safety with GraphQL
108+
- Good, because could achieve better type safety with GraphQL codegen (though currently we manually declare model shapes on both client and server, so we don't get this benefit today)
93109
- Good, because eliminates Apollo Cache manual update issues
94110
- Good, because maintains GraphQL tooling benefits
95111
- Bad, because requires significant backend refactoring

0 commit comments

Comments
 (0)