Distributed systems
Lock TTL must exceed worst-case tick duration
Lock TTL must exceed worst-case tick duration
DynamoDB conditional writes for multi-instance safety
DynamoDB conditional writes for multi-instance safety
attribute_not_exists (or similar conditions) on writes that must be idempotent across instances.Why it matters: Without conditional writes, a second instance can silently overwrite the first instance’s data. DynamoDB does not error on duplicate puts by default.Promise.allSettled over Promise.all for batch operations
Promise.allSettled over Promise.all for batch operations
Promise.allSettled() instead of Promise.all() when sending to multiple targets (e.g. APNs push tokens).Why it matters: Promise.all() rejects on the first failure, dropping the entire batch. One expired push token should not prevent delivery to every other device.Fire-and-forget async handlers swallow errors
Fire-and-forget async handlers swallow errors
void this.fn() without a .catch().Why it matters: Unhandled promise rejections from fire-and-forget calls are invisible — no logs, no alerts, no retries. The operation silently fails.Server-driven UI
Ship API display fields BEFORE building iOS cards
Ship API display fields BEFORE building iOS cards
Never re-process data the backend already formats
Never re-process data the backend already formats
prefix(3) to team codes truncated four-letter codes like PBKS to PBK.Bump schema version when MatchItemSchema changes
Bump schema version when MatchItemSchema changes
MatchItemSchema must include a schema version bump.Why it matters: iOS uses a disk cache keyed by schema version. Without a bump, devices running the old version will deserialize stale data and never see the update until the cache expires naturally.PR #328Environment & config
!!process.env.FLAG treats 'false' as truthy
!!process.env.FLAG treats 'false' as truthy
=== 'true'. Never rely on !! coercion.Why it matters: process.env.FLAG = 'false' is a non-empty string, so !!process.env.FLAG evaluates to true. This silently enables features you intended to disable.Centralized requireEnv() creates all-or-nothing coupling
Centralized requireEnv() creates all-or-nothing coupling
requireEnv() for every variable means one missing var (even for an unused feature) blocks the entire server from starting. This makes local development and partial deployments unnecessarily painful.PR #286iOS / Swift 6
Swift 6 synthesized Codable conflicts with Sendable
Swift 6 synthesized Codable conflicts with Sendable
nonisolated init(from:) and encode(to:) to structs that need both Codable and Sendable.Why it matters: Swift 6 synthesizes Codable conformance as main-actor-isolated on structs, which conflicts with Sendable generic constraints. This causes compile errors in concurrent contexts.ISO8601DateFormatter with .withFractionalSeconds returns nil for non-fractional timestamps
ISO8601DateFormatter with .withFractionalSeconds returns nil for non-fractional timestamps
ISO8601DateFormatter configured with .withFractionalSeconds returns nil for timestamps like 2024-01-15T10:30:00Z (no fractional part). This silently drops valid dates.Never gate follow-persistence on Live Activity checks
Never gate follow-persistence on Live Activity checks
areActivitiesEnabled() or similar LA-specific checks.Why it matters: The areActivitiesEnabled guard blocked the entire follow flow, meaning users who had Live Activities disabled could not follow matches at all. Follow persistence is independent of LA state.PR #338Store observation Tasks as instance properties on singletons
Store observation Tasks as instance properties on singletons
Task objects that observe published properties — assign them to instance-level properties on the owning singleton.Why it matters: If the Task is only stored as a local variable, ARC can deallocate it, silently stopping observation. This manifests as frozen token updates or missed state changes that are extremely hard to diagnose.LA platform knowledgePrivacy & telemetry
sendDefaultPii: true requires a beforeSend scrubber
sendDefaultPii: true requires a beforeSend scrubber
sendDefaultPii in Sentry, you must also configure a beforeSend hook that strips sensitive fields.Why it matters: Without a scrubber, Sentry events will contain user emails, IP addresses, and auth headers — a compliance and privacy violation.PR #335Audit every log site when bridging logger to telemetry
Audit every log site when bridging logger to telemetry
logger.info/warn/error call for PII.Why it matters: Logs that were safe when written to local stdout become a liability when forwarded to a third-party service. Emails, URLs with tokens, and device IDs all end up in external dashboards.PR #325Sanitize log payloads with an allowlist
Sanitize log payloads with an allowlist
Caching
Never have two caches for the same data
Never have two caches for the same data
Cache-miss compute is essential with multiple producers
Cache-miss compute is essential with multiple producers
Replay system
Mock services should return ALL data
Mock services should return ALL data
include parameters.Why it matters: When the backend adds a new include, the mock breaks because it only returns the fields it knew about at the time it was written. Return everything and let the caller filter.PR #322Replay fixtures must use current timestamps
Replay fixtures must use current timestamps
now, not hardcoded historical dates.Why it matters: Date-range queries (e.g. “matches today”) will never return fixtures with hardcoded past dates, making them invisible during testing.PR #319Document timing contracts between services explicitly
Document timing contracts between services explicitly
Process
Pre-push hooks: read remote refs from stdin
Pre-push hooks: read remote refs from stdin
git rev-parse. Users can bypass branch-name checks with git push origin HEAD:main.Why it matters: The hook receives the remote ref being pushed to via stdin. If it only checks the local branch name, direct pushes to protected branches slip through.PR #342Delete old code in the same PR that replaces it
Delete old code in the same PR that replaces it
ADRs for simplification are as valuable as ADRs for complexity
ADRs for simplification are as valuable as ADRs for complexity