I've trained two reactive rescue dogs from scratch using markers and a lot of cheese. Loose-lead walking, threshold distance, and why your recall falls apart in the park.
The same trick applies to anything expensive in a policy, not just auth.uid(). If your policy joins a memberships table, put the whole lookup in a security definer function and call it inside a subselect so it runs once. A policy that joins on every row is a nested loop over your tenant table that nobody ever profiles because it never appears in application code.
Rule of thumb I use: a policy predicate should compare a column against a constant. Anything more than that and it should be behind a function you can benchmark on its own.
The other half of this is that six panels are mounted when only one is visible. A tab layout that renders all tabs and hides them with CSS keeps every query in those tabs active forever - subscribed, stale, and refetching on focus for content nobody is looking at. Unmount the hidden ones. Query keeps the data around for gcTime so switching back is instant anyway, and your focus burst drops by whatever fraction of the panels are offscreen.
Half of this is a behaviour problem rather than a plant problem. Cats chew because they want something to chew, so give her a pot of cat grass and something like silvervine or a chew toy she actually likes, in a spot that is easier to reach than your shelves. Mine stopped stripping the spider plant within a fortnight of having her own tray of oat grass. Redirect first, then remove the genuinely dangerous ones, then worry about the rest.
Also check you only have one QueryClient. If it is constructed inside a component body rather than in a module or useState(() => new QueryClient()), you can end up with a client that gets replaced on re-render, and then you are invalidating a cache nothing is subscribed to any more. Rare with the app router templates, common in code that grew out of a tutorial.
It is a stage and day four is the worst of it. Soy typically needs one to two weeks to cure and there is a well known slump in the first week where cold throw drops before it comes back. Lids on, somewhere stable, smell them again at day 10 and day 14.
One thing to check though: 82C is fine for adding fragrance but two minutes of stirring is on the short side. Stir gently for a full two minutes minimum, longer for thick oils, and scrape the sides. Poorly bound fragrance smells great early and then disappears.
If you do add pullets to five year old hens, the old girls are usually less aggressive than a flock of two year olds but slower to accept anyone. Mine took about four weeks with a see but do not touch panel, two feeders and two waterers at opposite ends of the run, and I did not let them mix unsupervised until the pullets could outrun them. Do it in spring so the pullets come into lay while the weather is on your side.
Rolling two in every second year is the answer I wish someone had given me at the start. It also spreads the integration pain into small doses instead of one horrible fortnight.
If you log, log the postdrome separately from the pain. Two of my patterns only became visible once I counted those days as affected rather than as normal days.
Once you have the boundary in the right place, the next surprise is updates. Change the query key - swap the date range on that card - and you will get the skeleton flashing back over content that was already on screen. Wrap the state change in startTransition and React keeps the old UI up while the new data loads instead of tearing it down. useTransition also hands you an isPending you can use to dim the card.
We waited two years because of the price. By the time we booked, it was not couples counselling any more, it was two people negotiating an ending with a referee, which took longer and cost more than the thing we avoided. My honest read is that the cheapest version of this is the early version of it.
Any state update that causes a suspending component to suspend again. Wrap the setDateRange call in startTransition and React keeps the previous tree mounted until the new data resolves. The fallback only comes back for content that was never on screen in the first place.
On you, and it would be on you in Zustand too - that is a domain decision, not a library feature. Cheapest thing that works: send the updated_at you read with the mutation, have the server reject on mismatch with a 409 and the current row, and surface a "this changed while you were offline" screen. Two of you will not build merge semantics, and technicians would rather be told than silently overwritten.
Keep server data in the query cache. What you are describing - offline edits that sync later - is persistQueryClient plus paused mutations, and that is maybe 60 lines rather than a project.
The shape:
a persister writing the cache to IndexedDB, gcTime bumped well past your persist window or entries get thrown away before they are restored
onlineManager flips to offline, mutations queue instead of failing
each mutation gets a mutationKey and a registered mutationFn so resumePausedMutations() can replay them after a restart
optimistic updates so the technician sees their own edit immediately
Moving entities into Zustand means you now own fetching, caching, invalidation, deduping, retry and staleness by hand, in a two-person team, for 40 screens. I have done that migration in the other direction and it took a quarter.
The water thing is the whole game with ducks. I run mine off two builders trugs and swap them morning and evening rather than trying to keep one big pond clean, and it turned a daily hour into a daily five minutes.
Kids plus ducks is the part I would weight heaviest. Ducks do not want to be held and never will, and a child who wants a pet gets a bird that runs away for ten years. Get hens, get docile hybrids, and put the money into the run base.
The mental model that fixes this: the registrar is who you rent the name from, the nameservers say which company answers questions about the name, and the records inside the zone point at whoever runs each individual service. Those three are completely independent and can be three different companies.
When you change nameservers you are not moving the website, you are replacing the entire answer sheet. The new host's answer sheet has an A record for the site and nothing for mail, so mail stops.
My rule: pick one DNS provider deliberately, keep every zone there regardless of who hosts what, and never let a host talk you into moving nameservers as part of an onboarding wizard. Export the zone before you touch anything.
Keep a very simple log: wake time, first caffeine, and whether you got one. Three columns. After eight weeks the pattern is usually visible without any interpretation at all.
The summary endpoint is the obvious call in hindsight. The 8 widgets are 8 endpoints because 8 different people asked for them at different times, not because anything required it.
Test with the fragrance you actually sell. Different oils behave completely differently at the same load - vanilla heavy ones are notorious for needing a size up over something citrus. A wick that is perfect in one scent tunnels in another.
You mostly live with it, but you can push it a long way down.
It is thermal contraction. The wax shrinks as it cools, glass does not, and adhesion fails wherever the bond is weakest. Warming the jars to about 40C before pouring and then cooling slowly - a cardboard box over the whole batch overnight - gets me around nine clean jars in ten. Pouring hotter does not help; pouring into a cold jar in a 20C room is the main culprit.
Also worth saying: wet spots are cosmetic only. They do not affect burn, throw or safety. Commercial soy candles have them too, they just get sold before anyone notices.
Oven on its lowest setting for ten minutes, then out onto a towel. A heat gun gives you uneven jar temperature, which just moves the problem around the glass.