The Problem: Complexity Without Benefits
Three months ago at GLINR, our AI-powered developer platform was shipping 50kb of Apollo Client just to fetch billing quotas and user data.
As the lead architect (GDSKS here), I kept asking: "Are we actually using these features?" The answer was uncomfortable: we were using about 10% of what Apollo offered.
What We Actually Needed
The Metrics That Made Us Act
| Metric | Value | Status |
|---|---|---|
| Apollo Bundle | 50kb gzipped | Too large |
| Cache Complexity | High | Unused |
| Time to Interactive | 2.8 seconds | Slow |
| Developer Confidence | 6.2/10 | Low |
| Features Used | ~10% | Wasteful |
The Solution: Architectural Separation
The breakthrough came from a simple realization: server state and client state are fundamentally different.
The Core Principle
State Classification
| State Type | Characteristics | Best Tool | Example |
|---|---|---|---|
| Server State | Asynchronous, cached, needs sync | TanStack Query | API data, user info, billing |
| Client State | Synchronous, local, ephemeral | Zustand | Modals, themes, form wizards |
Architecture Deep Dive
Before: The Apollo Monolith
Pain Points:
- Mixed responsibilities (server + client state)
- Unclear patterns for UI state
- Complex cache invalidation
- 50kb bundle for basic queries
After: Clean Separation
Benefits:
- Clear separation of concerns
- Each tool optimized for its purpose
- 18kb total bundle
- Obvious patterns for developers
How Data Flows: The Complete Picture
Query Lifecycle with TanStack Query
State Updates with Zustand
Real Implementation at GLINR
The Code: Less Is More
Here's the minimal code needed to get started:
Setup TanStack Query (5 lines):
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient({
defaultOptions: { queries: { staleTime: 60000 } }
});
// Wrap app
Setup Zustand (8 lines):
import { create } from 'zustand';
export const useAppStore = create((set) => ({
activeOrgId: null,
theme: 'light',
setActiveOrg: (id) => set({ activeOrgId: id }),
setTheme: (theme) => set({ theme }),
}));
Using Both Together:
// Component code
const { data: quotas } = useQuery({
queryKey: ['quotas', orgId],
queryFn: fetchQuotas
});
const { theme, setTheme } = useAppStore();
That's it. Seriously.
The Migration Journey
Phase-by-Phase Approach
Decision Tree for State Placement
Production Results: The Numbers
Performance Gains
Developer Experience Impact
| Metric | Before | After | Change |
|---|---|---|---|
| Time to add feature | 4-6 hours | 1-2 hours | 67% faster |
| Developer confidence | 6.2/10 | 9.1/10 | 47% increase |
| Code review time | 45 min avg | 20 min avg | 56% faster |
| Onboarding new devs | 2 weeks | 3 days | 80% faster |
Cache Performance
Architecture Patterns We Learned
Store Organization
Query Key Strategy
When To Make This Switch
Decision Matrix
Good Fit Scenarios
| Scenario | Recommendation | Why |
|---|---|---|
| Simple GraphQL fetching | Migrate | TanStack Query is lighter, simpler |
| Building SPAs or dashboards | Migrate | Better cache control, less overhead |
| Team struggles with Apollo | Migrate | Much easier mental model |
| Need normalized caching | Stay | Apollo's strength |
| Heavy GraphQL subscriptions | Stay | Built-in support |
Key Takeaways
The Three Principles
Best Practices Checklist
- [ ] Separate server state from client state
- [ ] Use hierarchical query keys
- [ ] Keep Zustand stores focused and small
- [ ] Leverage TanStack Query's automatic caching
- [ ] Use TypeScript for type safety
- [ ] Set reasonable staleTime values
- [ ] Enable DevTools during development
- [ ] Monitor bundle size regularly
Resources & Next Steps
Official Documentation
- TanStack Query - Complete API reference
- Zustand - Simple state management
- GLINR Platform - Our AI developer tools
Community & Support
- TanStack Discord - Active community
- Zustand GitHub - Issues and discussions
Further Reading
- "Goodbye Redux? Meet TanStack Query" - Industry shift analysis
- "TanStack Start vs Next.js" - Framework comparison
- "Modern React Patterns 2025" - Current best practices
About GLINR & GLINCKER
GLINR is our AI-powered developer platform offering:
- Profanity detection with AI enhancement
- Text summarization via GCP NLP
- URL shortening and QR generation
- AI assistant services (upcoming)
GLINCKER is our parent brand building practical AI micro-tools for developers and businesses.
Connect & Follow
Topics I write about:
- Modern React architecture
- Full-stack development patterns
- AI/ML integration strategies
- Developer productivity
- Building scalable platforms
Share Your Experience
Have you migrated from Apollo? Using TanStack Query + Zustand in production? Share your story in the comments below.
Found this helpful? Please share with your team and clap if you enjoyed the read.
This article is part of the GLINCKER Engineering Series. More coming on Next.js 15 patterns, Spring Boot 3 architecture, and building AI-powered SaaS platforms on limited resources.
Tags: #React #StateManagement #TanStackQuery #Zustand #WebDevelopment #JavaScript #TypeScript #Architecture #Apollo #GraphQL #NextJS #Frontend #Performance #2025
Published by GDSKS • Lead Architect, Founder at GLINCKER • Building GLINR Platform
Last updated: November 2025















Top comments (0)