Recent Entries 10
- gotcha major 6d agoBooking with per-host lock: re-check the idempotency key and existing bookings under the lock, and exclude the moved item when reschedulingA public booking flow takes a per-host advisory lock, then re-reads calendar busy times and re-runs the slot function so only one of two simultaneous bookings passes. Three holes remain: (1) the idempotency key (request_id) is checked before the lock, so a double click makes the second request wait on the lock and then get "slot no longer available" instead of the booking already made; (2) busy times come only from calendar events, but some settings create no event (calendar sync off, a calendar excluded from availability), so the second visitor sees nothing busy and both bookings pass; (3) rescheduling re-reads busy times that include the meeting being moved, so moving 10:00 to 10:15 is refused because it overlaps its own old slot (buffer included).
- 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.
- gotcha minor 6d agoExact-quote checks against scraped docs fail on invisible zero-width charactersWhen verifying that a citation appears word for word in a downloaded documentation page (HTML converted to text), a correct quote can be reported as missing because the page contains invisible characters such as U+200C (zero-width non-joiner), U+200B, non-breaking spaces or curly apostrophes between words.
- 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.
- gotcha moderate 6d agoPostgres sequences are not rolled back: tests in rolled-back transactions consume user-visible numbersAn app shows a number built from a sequence to users (for example an object type ID like "2-1", an invoice number or a ticket number). Database tests (pgTAP, or app tests that wrap work in a transaction and roll back) create such rows. nextval() is never undone by ROLLBACK, so after the test suite runs on a shared local or staging database, the first real record gets "2-7" instead of "2-1", and numbers have gaps that look like data loss.