You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/adr/0047-remove-graphql-from-fxa-settings.md
+25-9Lines changed: 25 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# Remove GraphQL from fxa-settings
2
2
3
3
- 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
5
5
- Date: 2026-01-14
6
6
7
7
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
19
19
## Decision Drivers
20
20
21
21
-**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
22
26
-**Developer experience**: Cognitive load of maintaining two data-fetching paradigms
23
27
-**Testing complexity**: Apollo mocking vs direct auth-client mocking
24
28
-**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
33
37
34
38
## Decision Outcome
35
39
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.
37
45
38
46
### Positive Consequences
39
47
40
48
-**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
41
51
-**Simpler testing**: Direct auth-client mocking instead of Apollo MockedProvider
42
52
-**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
43
54
-**Native React state management**: Uses React 18's `useSyncExternalStore` for localStorage reactivity instead of Apollo Cache
-**Faster development**: No need to create GraphQL resolvers, mutations, and types for new features
46
57
-**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.
48
60
49
61
### Negative Consequences
50
62
51
63
-**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)
54
66
-**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)
56
68
57
69
## Pros and Cons of the Options
58
70
@@ -71,13 +83,17 @@ This is the status quo from ADR-0044 - prefer auth-client but keep GraphQL where
71
83
72
84
### Option B: Fully remove GraphQL from fxa-settings
73
85
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.
75
89
76
90
- Good, because single data-fetching pattern reduces cognitive load
77
91
- Good, because testing is simpler with direct auth-client mocks
78
92
- Good, because eliminates GraphQL service dependency for settings
79
93
- 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
81
97
- Good, because smaller bundle size without Apollo client
82
98
- Bad, because requires completing migration work
83
99
- 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
89
105
Refactor to use libs directly in graphql-api (deprecate auth-client), as described in FXA-8633.
90
106
91
107
- 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)
93
109
- Good, because eliminates Apollo Cache manual update issues
94
110
- Good, because maintains GraphQL tooling benefits
95
111
- Bad, because requires significant backend refactoring
0 commit comments