DEV Community

Cover image for Dev Log: 2026-07-02 — disable means drain, and case never matters
Nasrul Hazim Bin Mohamad
Nasrul Hazim Bin Mohamad

Posted on

Dev Log: 2026-07-02 — disable means drain, and case never matters

TL;DR

  • "Disable" should drain, not delete. Turning off a gateway route or an upstream target now blocks/redirects traffic gracefully instead of yanking config out from under live requests.
  • Case should never decide identity. Directory lookups and auth flows now normalise case so UPPER() mismatches stop causing phantom "user not found" and duplicate-account bugs.
  • A couple of sharp framework gotchas: a Blade compile quirk and a pgBouncer + PDO prepared-statement trap.
  • Standout of the day is a public one — accessible datatables — written up on its own.

Disable is a state, not a delete

Across an API-gateway management app I work on, the recurring theme today was the difference between removing something and disabling it.

Disabling a route shouldn't quietly deregister it and let in-flight requests fall through to nothing. It should install an explicit guard that terminates (or redirects) traffic while the route sits disabled — an off switch, not a shredder. Same idea for upstream targets: an Enable/Disable toggle now drains a target instead of deleting it from the pool, so connections finish instead of getting cut.

The lesson generalises: any "on/off" on live infrastructure wants three states in your head — active, draining, off — not a binary that maps "off" to "gone".

Case should never decide identity

The other thread ran through an enterprise identity portal. Directory backends are merciless about case: an Oracle-backed username, an LDAP attribute, and an email typed at login can all differ only in capitalisation and still be the same person. That mismatch shows up as "user not found", duplicate accounts, or a password reset that silently targets the wrong row.

The fix is boring and correct: normalise case at the boundary.

// Match on a case-folded column, not the raw input.
User::whereRaw('UPPER(email) = ?', [Str::upper($email)])->first();
Enter fullscreen mode Exit fullscreen mode

Do it consistently — lookups, login sync, password reset — and a whole category of "works for me / not for them" bugs disappears. If you can, back it with a functional index on UPPER(column) so the normalised lookup stays fast.

Two gotchas worth pocketing

Symptom Cause Fix
Number field renders invisible in a component @if placed inside a component tag's attributes skips compilation Move the conditional outside the tag, or use :attribute binding
Query fails behind a connection pooler pdo_pgsql server-side prepared statements clash with pgBouncer (transaction pooling) Disable server-side prepares on the connection

Both cost more debugging time than they should because the failure looks like something else — a styling bug, a flaky query — not a config mismatch.

Takeaway

Two ideas carried the day: disable is a lifecycle state, so drain don't delete, and case is not identity, so normalise at the edge. Neither is glamorous; both quietly remove an entire class of production surprises.

Top comments (0)