Today’s recommendations: BM25 search in Postgres, FrankenPHP monitoring with Ember, Laravel scheduled task pitfalls, a $20 SMS gateway, and streaming JSON in Symfony

Tiger Data's native BM25 extension for Postgres with 2-6x faster queries than ParadeDB, a zero-config terminal dashboard for Caddy and FrankenPHP, eight patterns for safe Laravel scheduled tasks, building a production SMS gateway on a cheap Android phone, and cutting Symfony memory usage 10x with streamed JSON responses.

A backend-heavy batch this time, databases, PHP infrastructure, and two scrappy engineering stories.

Tiger Data’s pg_textsearch 1.0 is the most significant Postgres extension launch I’ve seen this year. If you’ve used ts_rank for full-text search at scale, you know the pain: no inverse document frequency (common words carry the same weight as rare ones), no term frequency saturation (a document mentioning “database” 50 times ranks 50x higher than one mentioning it once), and no efficient top-k path. Most teams bolt on Elasticsearch as a sidecar. pg_textsearch takes a different approach, real BM25 scoring, written from scratch in C, stored entirely in standard Postgres pages. It participates in WAL, works with pg_dump and streaming replication, requires zero external infrastructure. The architecture uses an LSM-tree-inspired memtable that spills to immutable disk segments, with Block-Max WAND optimization for fast top-k retrieval. On 138M documents, two-term queries return top-10 results in 9ms, 6.5x faster than ParadeDB. The honest limitations section is refreshing: no phrase queries, OR-only semantics, no background compaction yet. But for anyone considering Elasticsearch as a search sidecar alongside Postgres, this changes the calculus.

Ember is what I’d describe as htop for your Caddy server. Zero configuration: run ember init, then ember, and you get a live terminal dashboard with RPS sparklines, latency percentiles (P50/P90/P95/P99), TTFB per host, color-coded status code breakdown, and in-flight request counts. If you use FrankenPHP, a second tab appears automatically showing per-thread status: busy/idle state, the URI being processed, request duration with color indicators, and memory usage per thread. Workers are grouped intelligently with queue depth and crash counters. You can restart workers directly from the dashboard. For production, there’s a daemon mode that exposes Prometheus-compatible /metrics and /healthz endpoints, plus ember diff for deployment regression detection (exit code 1 if performance dropped >10%). Built in Go, ~15MB RAM, MIT licensed. If you run FrankenPHP, install this today.

Laritor’s Mastering Scheduled Tasks in Laravel covers eight patterns that prevent real production incidents. The biggest gotcha people miss: Laravel runs scheduled tasks sequentially by default. If Task A takes 10 seconds, Task B is delayed by 10 seconds, silently. The fix is runInBackground(), which spawns each task as a separate PHP process. The post also covers withoutOverlapping() (prevents duplicate runs when a task exceeds its interval, critical for email-sending jobs), onOneServer() (essential when your scheduler runs on multiple servers, since withoutOverlapping alone isn’t enough), staggered cron expressions to spread resource load across a five-minute interval, conditional execution with skip() and environments(), output capture methods, and before/after hooks for pinging monitoring services. Each pattern includes the specific code and a clear explanation of the failure mode it prevents.

Building an SMS Gateway with a $20 Android Phone is scrappy engineering at its best. The author needed SMS capability without Twilio’s per-message costs. The solution: a cheap Android phone running an app that accepts HTTP requests and sends SMS through the native messaging stack. The walkthrough covers API design, self-imposed rate limiting (carriers will throttle you if you blast too fast), delivery receipt handling, and honest reliability data after months of real use. Not enterprise-grade, but genuinely useful for low-volume notification systems, personal alerts, and side projects where $0.0075/message adds up.

Native JSON Streaming in Symfony tackles a common production bottleneck: serializing large JSON API responses consumes memory proportional to response size. The fix uses Symfony’s StreamedJsonResponse to emit JSON incrementally, writing tokens to the output buffer instead of building the entire structure in memory. The result: 10x reduction in peak RAM for large responses. The implementation details, maintaining valid JSON while streaming, handling nested structures, error recovery mid-stream, are practical and well-benchmarked. If your Symfony API endpoints occasionally serve large payloads, this pattern is worth adopting.