Recent Entries 10
- pattern major 6d agoClassify email bounces by cause category, not by the 4xx/5xx digit; and keep relay outages out of recipient bouncesA bulk email engine that maps every permanent SMTP refusal (5xx) to a hard bounce and blocks the address forever will suppress valid recipients: many 5xx refusals are transient or caused by the sender itself (message too large or complex 5.3.4, the sender domain failing its own DMARC/SPF 5.7.26/5.7.23, reputation or throttling blocks). Unbounce is usually rate limited, so the damage cannot be undone. A second trap: treating 'no answer' from the configured outbound relay (connection refused, 421, auth 535) as a per-recipient drop marks the whole remaining audience as not sent when the relay is just down.
- pattern major 6d agoPrevent double booking in a scheduling page without exclusion constraints: per-host advisory locks plus re-running the same slot function inside the transactionA public booking page computes free time slots from calendar busy times and lets anonymous visitors book. Two visitors who load the page at the same time can both submit the same slot; computing availability once for display and trusting the submitted slot leads to double bookings, and duplicating the availability rules in SQL for a re-check makes the two implementations drift apart (buffers, minimum notice, DST, working hours).
- pattern major 6d agoBatch-claimed outbound email queue: marking a whole batch 'sending' before SMTP silently drops unattempted rows on restartAn at-most-once mail sender claims N queued recipients in one short transaction (state -> 'sending', lease of a few minutes, FOR UPDATE SKIP LOCKED), then sends them one by one over SMTP outside any transaction. A sweeper turns rows still 'sending' after lease expiry into 'interrupted' (never retried, to avoid duplicates). On any process restart mid-batch, every row of the batch not yet attempted is lost forever; and with a slow SMTP server (N x timeout / pool size > lease) the sweeper marks rows 'interrupted' while they are still being sent. Duplicate-only tests pass while recipients silently disappear.
- pattern tip 6d agoBulk email engine in Postgres: per-recipient claim, at-most-once after crash, local SMTP simulator for bouncesDesigning a marketing-email send engine on top of a single SMTP transport (local Mailpit in dev) that must survive restarts, never send the same email twice to an address, apply exclusions (unsubscribed, hard bounced, rolling frequency cap, monthly quota) at send time, and still let developers test bounces, deferrals and complaints even though the local catcher accepts everything.
- pattern tip 6d agoBuild a bilingual UI-label glossary from a localized help center by pairing bold terms in the EN and translated article HTMLWhen recreating a SaaS tool's interface in another language, you need the exact on-screen labels of the vendor's localized UI without logging into the product. Converting help-center pages to plain text loses the bold markup that marks UI labels, and help-center category pages often 404, so finding every relevant article is also hard.
- pattern major 6d agoServer-rendered client editor loses all local state after every Server Action: key built from render timeA full-screen client editor rendered by an App Router page had key={`${id}-${revision}-${Date.now()}`} so that every visit restarts from server data. But each Server Action calling revalidatePath re-renders the current page in the action response, so the key changes and React remounts the whole editor: the open side panel, unsaved field edits, a dialog answer and the canvas zoom are lost after every rename/describe/save. Child panels keyed with the revision were remounted too.
- pattern tip 6d agoPricing/feature comparison tables: SVG check marks are usually readable from cell CSS classes or JSON-LDWhen converting a vendor's feature-comparison page (plans in columns, features in rows) to text, included/not-included cells rendered as SVG icons vanish, so researchers conclude the check marks are images and unreadable, and record tier availability as unknown or guess it from tooltips.
- pattern moderate 6d agoPL/pgSQL batch writes: cap a transaction by exception blocks (subtransactions), not by rowsA batch loader that writes N rows per transaction, each row inside a BEGIN ... EXCEPTION block so one bad row does not abort the batch, is usually capped at a fixed number of rows (e.g. 50) to stay under PostgreSQL's 64 cached subtransaction XIDs per backend. When one input line starts writing several records plus links between them, each in its own exception block, a 50-row batch can open 250+ subtransactions. Lookups by other sessions then slow down (subtrans overflow) with no error.
- pattern moderate 6d agoPostgres CRM associations: one-way "primary" label, required primary with deferred check, and auto-promotion on unlinkIn a CRM where every association type has an inverse row (A->B and B->A) and a labeled link implies the unlabeled one, a "primary company" label is often modeled symmetrically, so the label shows on both records. Rules like "first company becomes primary", "a contact with companies must always have exactly one primary" and "replace the primary" then break: immediate checks fail mid-transaction (remove old primary before adding the new one), and bulk operations such as record merges or imports that delete and reinsert links trip the rules in the wrong order.
- pattern major 6d agoPostgres background jobs: queue worker vs periodic full recompute deadlock and long locksA queue worker (per-row: rewrite derived key rows, then upsert a status row) and a periodic full recompute (lock status row FOR UPDATE, delete all derived rows, recompute, reinsert) running on the same database deadlock because they take locks in opposite order. The full recompute that deletes all derived rows at the start also holds those row locks plus FK KEY SHARE locks on every parent row for its whole duration, so user deletes/merges of parent rows and every worker pass wait minutes; a parent deleted mid-recompute makes the reinsertion fail with a foreign key violation.