Most monorepo guides stop at folder structure. The real work is figuring out what belongs in apps versus packages, why a config-driven inventory beats a hardcoded one, and where the boundaries actually need to exist so you don't end up with spaghetti across your workspace.
Most guides skip the part where PHNET requires government recognition papers ā not SEC or BIR ā and Google Workspace for Education has a separate signup flow from Workspace Business. Claiming your domain under the wrong account costs days of support back-and-forth.
Google Workspace Education.edu.phPHNETDNSPhilippines
Page view analytics didn't show where 40% of students were dropping out of enrollment. Custom PostHog funnel events did. Upstash Redis handled edge rate limiting that standard Redis couldn't ā no persistent TCP connection needed. What each tool actually delivered.
Bot probes for /wp-admin and /.env were hitting Supabase auth on every request ā 400 unnecessary API calls in 2 minutes from a single scanner. Ordering middleware checks by cost (regex first, Supabase last) cut 60% of those calls before they reached auth.
If-else chains in page components break at four roles and enforce nothing at the API layer. Two enforcement points ā middleware prefix guards and per-server-action requireAuth checks ā plus a critical Supabase gotcha: reading role from user_metadata lets users escalate their own privileges.
Prisma timed out at 20K record uploads and ran 4 separate database fetches where SQL needed one JOIN. Switching to MySQL2 with raw queries cut upload failures to zero and dropped report load times from 2 minutes to 35 seconds.
Per-request connections worked fine in development. In production with 32 PM2 workers across 8 brands, connection overhead became the bottleneck ā not CPU or memory. The createPool settings that eliminated connection errors under peak concurrent load.
The morning report fetched a list of 100 stores, then ran a separate aggregation query for each one ā 101 round trips per page load, every day. A single JOIN with GROUP BY replaced all 101 queries and dropped load time from 3+ seconds to under 40ms.
20,000 individual INSERT/UPDATE queries meant 20,000 round trips ā at 2ms each, that's 40 seconds of network overhead before any query work. Multi-row VALUES INSERT and CASE WHEN UPDATE collapsed 20K queries to 14 and cut upload time to 8 seconds.
Adding an index on every column creates write overhead without solving anything. On a 500K-row system, EXPLAIN showed full table scans on multi-column WHERE clauses ā individual column indexes wouldn't have helped. Here's how to read the query patterns and place composite indexes correctly.
A single-pass CSV loader failed in three ways at 30K rows: duplicates, partial commits on crashes, and 120K extra queries from inline inventory sync. A 5-phase pipeline inside one transaction fixed all three and now processes 30K rows in 8 seconds.
Array.find() inside a loop that runs 20K times means up to 400 million comparisons ā O(n²). The insert queries were fast; the JavaScript between them was the bottleneck. Switching to JavaScript Map for O(1) lookups made the CPU cost negligible.
Switching from Prisma to raw MySQL2 means your query results become RowDataPacket[] ā effectively any[]. Hand-writing interfaces creates two sources of truth that will drift. Using Prisma-generated types as casts on MySQL2 results gives you full type safety from a single schema source.
Morning MOS reports took 2 minutes because of a full table scan, 101 queries per page load, and a JOIN column type mismatch. Three targeted fixes ā composite indexes, a single GROUP BY query, and a type normalization ā cut it to 30ā40 seconds.
Eight forks would have meant eight bug fixes and eight deployments every time. A JSON config file, PM2 cluster mode, and a MySQL2 migration instead turned a 2-week-per-brand onboarding into under 5 minutes ā while cutting memory per upload from 2 GB to 128 MB.
A Next.js app running as a single process was using 25% of a 4-core server. Switching to PM2 cluster mode with 4 workers per brand pushed throughput from ~100 to ~800 req/sec and uptime from 95% to 99.95% ā without buying new hardware.
Loading 30K CSV rows in one pass consumed over 2 GB per upload ā two concurrent uploads crashed the server. Processing in chunks of 3,000 with per-batch transactions dropped memory to 128 MB and brought out-of-memory errors to zero.
Manual stock reconciliation across 4 inventory tables took 2 days per week ā 104 hours a month of cross-referencing spreadsheets. A single ACID transaction that updates all 4 tables in order cut that to under 1 hour daily with a full audit trail.
Every tab switch in the dashboard triggered a fresh API call ā same data, same response, fetched again. A 5-minute staleTime, 30-minute cacheTime, and disabled refetchOnWindowFocus cut redundant API requests by 70% and made repeat views instant.
Cloud deployment hides process management, restarts, and connection handling behind platform defaults. Deploying on a client's 4-core server with no managed services made every one of those assumptions explicit ā and forced better infrastructure decisions upfront.
Five operational roles, one codebase ā without turning every page into a wall of conditionals. Module-level visibility gates and action-level permission checks kept the interface useful for each team without exposing what shouldn't be seen.
Internal tools fail because developers build what they think the workflow should be, not what it is. Watching the team work first, targeting the highest manual cost, and designing for exception cases upfront is what keeps systems in use after month three.
Business SystemsSoftware DeliveryOperationsProduct Engineering