Year in Review: The Full-Stack Patterns That Actually Held Up in 2024
I shipped seven projects this year. Some went great. Two crashed hard. Here's what I learned the hard way, so you don't have to.
What Actually Worked
Zustand over Redux. I know, I know — Redux Toolkit is fine. But I migrated three apps to Zustand and every single developer thanked me. The mental model just clicks. No providers, no action creators, no thunks. Just a store and some functions.
// This is genuinely all my team needed to understand
const useCart = create((set) => ({
items: [],
addItem: (item) => set((state) => ({ items: [...state.items, item] })),
}));
React Query for server state. I stopped fighting caching. React Query just works. One of my apps made 47% fewer API calls after switching because deduping handled itself. My backend team stopped complaining about duplicate requests.
**tRPC in monorepos. We had three Next.js apps sharing one set of types. REST would've been a nightmare. tRPC gave us confidence to refactor without fear. The type errors caught me more times than I'd like to admit.
What Bites Me Regularly
AI features before metrics. I built a nice chatbot in April. Nobody used it. I spent three weeks on RAG pipelines for a feature that needed two days of prompt engineering. Now I have a rule: launch with GPT-4o-mini and zero caching. If people use it, I invest. Most don't.
Over-optimizing the first two weeks. I rewrote a dashboard with Redux Toolkit, RTK Query, and a custom websocket layer. Took two weeks. The simpler version with Context and useEffect would have taken two days. The complex version crashed in production. The simple version is still running.
##The Surprising Wins Apple Intelligence found real users. I thought the on-device stuff was gimmicky. Then I added a local summarizer for meeting notes. People actually used it because it was instant and private. No API key, no latency, no cost. I should have built more small on-device features.
Hydrogen 2.0 just worked. I migrated a client store over a weekend. The Remix foundation meant every React pattern applied. My team stopped asking "how do I do X in Hydrogen?" and started shipping. That's the sign of a good framework.
What I'd Do Differently
Start with the dumbest solution. My 2025 rule: build it without AI first. Add AI only when the heuristic fails. Most times, the heuristic never fails.
Say no to new state management. I don't need another store library. Zustand + React Query + Context covers everything. Adding Jotai for one feature created more confusion than value.
Read the migration guides thoroughly. I upgraded Next.js 14 to 15 without reading about async params. Broke 12 routes in staging. My team was not happy. The codemod would have saved me three hours.
The Numbers That Matter
Looking back across all projects:
| Pattern | Projects | Kept It | Dropped It |
|---|---|---|---|
| Zustand + React Query | 6 | 6 | 0 |
| tRPC | 4 | 4 | 0 |
| Custom API layer | 3 | 0 | 3 |
| AI without metrics | 4 | 1 | 3 |
| Redux | 2 | 0 | 2 |
I kept every project that started simple. I re-wrote every project that started complex.
Final Thoughts
2024 taught me that boring tech wins. Zustand is boring. React Query is boring. tRPC after a month feels boring. That's the point. I stopped chasing "modern" and started shipping. My stress levels dropped. My velocity went up.
For 2025, I'm picking the stack that lets me sleep at night. That means fewer dependencies, more defaults, and a hard rule: if I can't explain it to a junior dev in five minutes, I probably shouldn't use it.
The best pattern this year wasn't technical. It was waiting two weeks before optimizing anything. You'd be surprised how many "performance problems" disappear when you just ship and measure.