|
| 1 | +# Remove GraphQL from fxa-settings |
| 2 | + |
| 3 | +- Status: proposed |
| 4 | +- Deciders: Vijay Budhram, Lauren Zugai, Dan Schomburg, Barry Chen, Valerie Pomerleau |
| 5 | +- Date: 2026-01-14 |
| 6 | + |
| 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. |
| 8 | + |
| 9 | +## Context and Problem Statement |
| 10 | + |
| 11 | +In [ADR-0016](0016-use-graphql-and-apollo-for-settings-redesign.md) (2020), FxA adopted GraphQL and Apollo for the Settings Redesign project. The chosen approach was "Option B" - layering GraphQL on top of existing REST architecture via `fxa-graphql-api` as a proxy to `fxa-auth-server`. |
| 12 | + |
| 13 | +Four years later, [ADR-0044](0044-use-rest-over-gql-when-convenient.md) (2024) acknowledged that the GraphQL experience had been "a mixed bag" and established a preference for using `auth-client` for new network requests. However, ADR-0044 stopped short of committing to remove GraphQL entirely, citing concerns about level-of-effort and potential future framework changes (NextJS). |
| 14 | + |
| 15 | +This ADR evaluates whether to complete that migration by fully removing GraphQL from fxa-settings, or to maintain the current mixed approach. |
| 16 | + |
| 17 | +**Key question**: Should we fully remove GraphQL and Apollo from fxa-settings? |
| 18 | + |
| 19 | +## Decision Drivers |
| 20 | + |
| 21 | +- **Operational complexity**: Running and maintaining `fxa-graphql-api` as a separate service |
| 22 | +- **Developer experience**: Cognitive load of maintaining two data-fetching paradigms |
| 23 | +- **Testing complexity**: Apollo mocking vs direct auth-client mocking |
| 24 | +- **State management**: Apollo Cache reactivity vs localStorage with `useSyncExternalStore` |
| 25 | +- **Performance**: Direct auth-server calls vs GraphQL proxy overhead |
| 26 | +- **Future flexibility**: Positioning for potential NextJS migration |
| 27 | + |
| 28 | +## Considered Options |
| 29 | + |
| 30 | +- **Option A**: Maintain current mixed GraphQL/auth-client approach (status quo from ADR-0044) |
| 31 | +- **Option B**: Fully remove GraphQL from fxa-settings, use auth-client + localStorage with useSyncExternalStore |
| 32 | +- **Option C**: Go "all-in" on GraphQL by refactoring to use libs directly in graphql-api |
| 33 | + |
| 34 | +## Decision Outcome |
| 35 | + |
| 36 | +TBD |
| 37 | + |
| 38 | +### Positive Consequences |
| 39 | + |
| 40 | +- **Reduced operational complexity**: No need to run/maintain `fxa-graphql-api` for settings |
| 41 | +- **Simpler testing**: Direct auth-client mocking instead of Apollo MockedProvider |
| 42 | +- **Clearer data flow**: Components → auth-client → auth-server (no GraphQL proxy layer) |
| 43 | +- **Native React state management**: Uses React 18's `useSyncExternalStore` for localStorage reactivity instead of Apollo Cache |
| 44 | +- **Smaller bundle size**: Removing `@apollo/client` dependency (~100KB+ gzipped) |
| 45 | +- **Faster development**: No need to create GraphQL resolvers, mutations, and types for new features |
| 46 | +- **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 |
| 48 | + |
| 49 | +### Negative Consequences |
| 50 | + |
| 51 | +- **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 |
| 54 | +- **Requires server changes**: Auth-server endpoints must return all needed data (consolidated endpoints) |
| 55 | +- **Testing patterns change**: Teams must learn new mocking patterns |
| 56 | + |
| 57 | +## Pros and Cons of the Options |
| 58 | + |
| 59 | +### Option A: Maintain current mixed GraphQL/auth-client approach |
| 60 | + |
| 61 | +This is the status quo from ADR-0044 - prefer auth-client but keep GraphQL where already set up. |
| 62 | + |
| 63 | +- Good, because no additional migration work required |
| 64 | +- Good, because preserves existing GraphQL investments |
| 65 | +- Good, because maintains flexibility to go either direction |
| 66 | +- Bad, because developers must understand two data-fetching paradigms |
| 67 | +- Bad, because Apollo Cache manual updates are error-prone and cause bugs |
| 68 | +- Bad, because tests require both Apollo mocks and auth-client mocks |
| 69 | +- Bad, because `fxa-graphql-api` service must continue running |
| 70 | +- Bad, because new features face decision fatigue (use GQL or auth-client?) |
| 71 | + |
| 72 | +### Option B: Fully remove GraphQL from fxa-settings |
| 73 | + |
| 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. |
| 75 | + |
| 76 | +- Good, because single data-fetching pattern reduces cognitive load |
| 77 | +- Good, because testing is simpler with direct auth-client mocks |
| 78 | +- Good, because eliminates GraphQL service dependency for settings |
| 79 | +- Good, because consolidated `/account` endpoint reduces API calls (9 → 3) |
| 80 | +- Good, because positions codebase well for NextJS migration |
| 81 | +- Good, because smaller bundle size without Apollo client |
| 82 | +- Bad, because requires completing migration work |
| 83 | +- Bad, because replaces Apollo Cache reactivity with custom `useSyncExternalStore` + localStorage pattern |
| 84 | +- Bad, because loses GraphQL playground and self-documenting schemas |
| 85 | +- Bad, because requires understanding `useSyncExternalStore` pattern for localStorage reactivity |
| 86 | + |
| 87 | +### Option C: Go "all-in" on GraphQL |
| 88 | + |
| 89 | +Refactor to use libs directly in graphql-api (deprecate auth-client), as described in FXA-8633. |
| 90 | + |
| 91 | +- Good, because eliminates mixed paradigm by going fully GraphQL |
| 92 | +- Good, because achieves end-to-end type safety with GraphQL |
| 93 | +- Good, because eliminates Apollo Cache manual update issues |
| 94 | +- Good, because maintains GraphQL tooling benefits |
| 95 | +- Bad, because requires significant backend refactoring |
| 96 | +- Bad, because may conflict with NextJS migration plans |
| 97 | +- Bad, because increases GraphQL service complexity |
| 98 | +- Bad, because moving away from GQL later would be very expensive |
| 99 | +- Bad, because requires migrating auth-client usage back to GraphQL |
| 100 | + |
| 101 | +## Links |
| 102 | + |
| 103 | +- Previous ADRs: |
| 104 | + - [ADR-0016: Use GraphQL and Apollo for Settings Redesign](0016-use-graphql-and-apollo-for-settings-redesign.md) |
| 105 | + - [ADR-0044: Use REST over GQL when convenient](0044-use-rest-over-gql-when-convenient.md) |
| 106 | + - [ADR-0039: Use container component pattern](0039-use-react-container-component-abstraction.md) |
| 107 | +- Related tickets: |
| 108 | + - [FXA-8633: Epic for moving away from auth-client in graphql-api](https://mozilla-hub.atlassian.net/browse/FXA-8633) |
| 109 | + - [FXA-10861: Create auth-client wrapper](https://mozilla-hub.atlassian.net/browse/FXA-10861) |
0 commit comments