Ten anti-patterns of admin-console frameworks
From mistakes we actually made; every one of them can be traced to a line in the source.
Permission codes scattered as literals everywhere. By the time you want to close that gap, you cannot. Central definitions are not fastidiousness; they are the only thing that makes build-time verification possible.
Writing business, assembling conditions and querying in the controller looks faster, until the second requirement arrives and it becomes a lump nobody dares to touch.
Putting the transaction annotation wherever it is most convenient rather than at the boundary. Nobody notices when it stops working, until the numbers do not add up.
Allowing NULL in the soft-delete column, so `is_deleted = 0` never returns everything — one nullable column buys you the hardest bug of the year.
Hand-written SQL that bypasses the single exit. You win once, then you have to remember it again on every change.
Editing a migration script after it shipped. It runs locally and explodes in production; the freeze rule exists for exactly this.
Not passing the traceId into async entry points. The logs fill with broken threads and you can only guess when something goes wrong.
Caching with no way to observe it, which is staking correctness on luck.
Maintaining API documentation by hand. Three months later it has parted ways with the code.
Pushing business into the core repository, which turns every upgrade into surgery.