<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chizee</title>
    <description>The latest articles on DEV Community by Chizee (@chizee).</description>
    <link>https://dev.to/chizee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4066137%2Fea432cc9-6883-4e71-afc0-40c7345c5ead.png</url>
      <title>DEV Community: Chizee</title>
      <link>https://dev.to/chizee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chizee"/>
    <language>en</language>
    <item>
      <title>Stop Recomputing Your Dashboard on Every Page Load</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 27 Sep 2026 10:11:50 +0000</pubDate>
      <link>https://dev.to/chizee/stop-recomputing-your-dashboard-on-every-page-load-5b60</link>
      <guid>https://dev.to/chizee/stop-recomputing-your-dashboard-on-every-page-load-5b60</guid>
      <description>&lt;p&gt;A dashboard that runs a heavy aggregation against live tables works fine in a demo and then crawls in production, because every single page load recalculates the same numbers from scratch. The usual fix is piping everything into a dedicated warehouse like Snowflake purely so the dashboard has something fast to read.&lt;/p&gt;

&lt;p&gt;For a huge share of "internal dashboard" use cases, a materialized view does the same job with zero new infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-bake the aggregation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;daily_revenue&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;date_trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'day'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;revenue&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;daily_revenue&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;day&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That unique index is not optional decoration — I confirmed this directly by dropping it and trying to refresh: Postgres refuses outright with &lt;code&gt;cannot refresh materialized view "daily_revenue" concurrently&lt;/code&gt;, and tells you exactly why. It's the single most common way this recipe trips people up, so build the index in from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refresh without locking out readers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;REFRESH&lt;/span&gt; &lt;span class="n"&gt;MATERIALIZED&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;CONCURRENTLY&lt;/span&gt; &lt;span class="n"&gt;daily_revenue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;CONCURRENTLY&lt;/code&gt; recalculates in the background and hot-swaps only the changed rows into place — anyone reading the view mid-refresh sees the old data until the swap completes, never a lock, never a blank dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;daily_revenue&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;day&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your dashboard just reads this like any other table. No ETL pipeline, no separate job runner — the "transform" step &lt;em&gt;is&lt;/em&gt; the view definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put it on a schedule with zero extra infrastructure
&lt;/h2&gt;

&lt;p&gt;If you have &lt;code&gt;pg_cron&lt;/code&gt; available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'refresh-daily-revenue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'*/15 * * * *'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'REFRESH MATERIALIZED VIEW CONCURRENTLY daily_revenue'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scheduled refresh, running inside the database you already have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats a dedicated warehouse for most dashboards
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No ETL pipeline to babysit — the transform step is a SQL view.&lt;/li&gt;
&lt;li&gt;Dashboards stay fast as data grows, since they're reading pre-computed numbers, not raw transaction history.&lt;/li&gt;
&lt;li&gt;You control the refresh cadence directly — hourly, nightly, or on demand, it's one command either way.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Snowflake still wins
&lt;/h2&gt;

&lt;p&gt;Ad-hoc analytical queries across terabytes of historical data, joining many large fact tables in ways your operational schema was never modeled for. If your "warehouse" need is really "make this one dashboard fast," you may not need one.&lt;/p&gt;




&lt;p&gt;This is one of eight infrastructure swaps in &lt;strong&gt;Just Use Postgres&lt;/strong&gt;, a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance before it went in the book.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Get the field manual&lt;/strong&gt; — launch price &lt;strong&gt;$14&lt;/strong&gt; instead of paying a warehouse to pre-compute two numbers: &lt;a href="https://payhip.com/omenabyte" rel="noopener noreferrer"&gt;https://payhip.com/omenabyte&lt;/a&gt;&lt;br&gt;
🐳 Or take the &lt;strong&gt;$24 bundle&lt;/strong&gt; with the full &lt;code&gt;docker-compose up&lt;/code&gt; starter repo — all 8 modules as tested, runnable migrations + seed data: &lt;a href="https://4693433176360.gumroad.com/" rel="noopener noreferrer"&gt;https://4693433176360.gumroad.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Read this on omenabyte.com → &lt;a href="https://omenabyte.com/blog/replace-snowflake-dashboards-with-materialized-views" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-snowflake-dashboards-with-materialized-views&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>analytics</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>You're Doing Vibe-Coding Wrong. Here's the 17-Point Fix.</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 20 Sep 2026 10:59:39 +0000</pubDate>
      <link>https://dev.to/chizee/youre-doing-vibe-coding-wrong-heres-the-17-point-fix-e9h</link>
      <guid>https://dev.to/chizee/youre-doing-vibe-coding-wrong-heres-the-17-point-fix-e9h</guid>
      <description>&lt;p&gt;Nobody tells you this about the app you shipped last weekend: it's probably leaking.&lt;/p&gt;

&lt;p&gt;Not "might be" leaking. Probably leaking right now, to anyone who opens DevTools and spends four minutes looking. That isn't a scare tactic. Multiple independent scans run over the past year against thousands of AI-built apps landed on the same conclusion, and the details get worse the further you read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the scanners actually found
&lt;/h2&gt;

&lt;p&gt;Three research groups scanned thousands of AI-generated web apps built with Lovable, Bolt, v0, Replit, and Cursor. The numbers line up uncomfortably well.&lt;/p&gt;

&lt;p&gt;Vibe App Scanner ran 1,215 scans across 1,119 distinct apps between December 2025 and August 2026. 10.4% had at least one critical issue. 31.1% had something critical or high severity. Of the 359 apps using Supabase, which was 29.5% of the sample, 141 of them had a row-level-security or data-exposure problem that let information be read without authorization. That's 39.3%.&lt;/p&gt;

&lt;p&gt;Symbiotic Security crawled 65,643 URLs, confirmed 1,085 Supabase-backed sites, and scanned 1,072 of them. They logged 6,185 vulnerabilities. 98% of sites had at least one. 16% had a critical one. Only 26 of the 1,072 came back completely clean.&lt;/p&gt;

&lt;p&gt;Worth stating plainly: that 98% applies to Supabase-backed apps in their sample, not every AI-built app everywhere. And Vibe App Scanner flags its own bias in the other direction — their apps were voluntarily submitted by owners who already suspected a problem, so those rates over-represent risk, and 83% of their scans were the reduced quick-scan set. Their words: every prevalence number is a floor, not a ceiling. Read the two studies together and the honest read is "unusually bad, uncertain how bad."&lt;/p&gt;

&lt;p&gt;Two percent clean. That's the rate in the larger sample.&lt;/p&gt;

&lt;h2&gt;
  
  
  The specific failures
&lt;/h2&gt;

&lt;p&gt;172 sites let anyone delete records from the database without logging in. One DELETE request using the public key wipes entire tables.&lt;/p&gt;

&lt;p&gt;39 sites had tables fully readable by anyone holding the Supabase anon key, which is embedded in the page's JavaScript by design. So "holding it" just means "viewed source." Among those tables: &lt;code&gt;payments&lt;/code&gt;, &lt;code&gt;admin_users&lt;/code&gt;, and &lt;code&gt;chat_messages&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;308 sites exposed the anon key in JavaScript. On its own that's expected, it's a public key. The problem is what happens when no RLS policy exists behind it.&lt;/p&gt;

&lt;p&gt;34 sites had columns containing emails, hashed passwords, auth tokens, and phone numbers, all directly queryable through the Supabase REST API.&lt;/p&gt;

&lt;p&gt;None of this is theoretical. CVE-2025-48757 is the one that made headlines. A researcher scanned 1,645 apps from Lovable's official showcase, found 170 with critical flaws, and the same root cause kept showing up. Missing row-level security. MITRE scored it CVSS 9.3 Critical, though Lovable disputes the rating on the grounds that each customer is responsible for their own app's data, and the researcher later published his own scoring at 8.26. NVD lists the record as disputed. The vulnerability itself, insufficient RLS in generated sites through April 2025, isn't in dispute.&lt;/p&gt;

&lt;p&gt;Separately, a February 2026 report found an EdTech app with 16 vulnerabilities, 6 of them critical. 18,697 user records exposed, including 14,928 unique emails and 4,538 student accounts from K-12 schools plus UC Berkeley and UC Davis. The auth logic was inverted. It blocked logged-in users and let anonymous visitors straight through.&lt;/p&gt;

&lt;p&gt;Then there's Moltbook, an AI-agent social network. Wiz Research found zero RLS on any table. 1.5 million API tokens for OpenAI and Anthropic, 35,000 email addresses, and private messages, all reachable with the public key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this keeps happening
&lt;/h2&gt;

&lt;p&gt;Supabase turns row-level security off by default when you create tables through SQL. The Dashboard Table Editor defaults to on, but AI coding tools generate SQL migrations. They don't click through a Dashboard. So every table the AI creates starts unprotected.&lt;/p&gt;

&lt;p&gt;There's a documented pattern for what follows, called the fix loop. Palo Alto's Unit 42 described it. The AI writes a query, PostgreSQL returns error 42501 (insufficient privileges, which is RLS doing exactly its job), and the AI "fixes" the error by dropping the RLS policy. The query works. The table is now open. Nobody notices, because the app appears to function.&lt;/p&gt;

&lt;p&gt;Carnegie Mellon measured the underlying gap. 61% of AI-generated code is functionally correct, but only 10.5% is secure. Auth code is where that difference draws blood.&lt;/p&gt;

&lt;p&gt;It isn't only Supabase either. 38 apps across all platforms shipped hardcoded API keys in their JavaScript bundles. On Bolt.host, 17 of 251 apps. On Vercel's AI-generated apps, 18 of 67, which is 26.9%. One Replit app shipped Anthropic, OpenAI, and Google keys at the same time. Those keys bill per token. A leaked OpenAI key powering a loop can burn hundreds of dollars overnight.&lt;/p&gt;

&lt;p&gt;Security headers are missing almost everywhere. 93.6% of scanned apps had no Cross-Origin-Resource-Policy. 78.4% had no Content-Security-Policy. 70.6% had no X-Frame-Options.&lt;/p&gt;

&lt;p&gt;The common thread, as one report put it: AI code generators optimize for "does it work?" and not "is it safe?" Your prompt never said "add auth middleware to every endpoint" or "never embed API keys client-side," because neither is a functional requirement. The code works perfectly in a demo and fails catastrophically in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 17-point checklist
&lt;/h2&gt;

&lt;p&gt;Work through this list. It applies whether you built with Lovable, Bolt, v0, Cursor, Replit, or by hand.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Protect admin routes.&lt;/strong&gt; Every admin path needs an auth check on the server, not a hidden link or a client-side conditional. If the route renders, the route is reachable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-side permissions.&lt;/strong&gt; Authorization decisions belong on the server. Anything the browser enforces, the browser can edit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enable RLS.&lt;/strong&gt; Run &lt;code&gt;ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;&lt;/code&gt; for every table in the public schema, then &lt;code&gt;ALTER TABLE your_table FORCE ROW LEVEL SECURITY;&lt;/code&gt; so policies can't be bypassed. RLS with no policies locks the table entirely, which is safe but probably not what you intended. Write policies scoped to the row's owner, not to "any authenticated user." Then &lt;strong&gt;verify as anon&lt;/strong&gt;, not as a logged-in test user. Most of the data-exposure findings above exist because the check was skipped for the anonymous public key, which is embedded in your page's JavaScript by design. One read is enough: &lt;code&gt;const supabase = createClient(url, anonKey); const { data } = await supabase.from('payments').select('*').limit(1);&lt;/code&gt; Returning rows before anyone signs in is the tripwire. It also catches the policy-exists-but-does-nothing case: &lt;code&gt;using (true)&lt;/code&gt; on a select passes an RLS-enabled scan while exposing every row to anon. Enabled is not the same as enforced.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify email addresses.&lt;/strong&gt; A confirmation flow that doesn't confirm anything is decoration. Turn it on and test it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hash passwords securely.&lt;/strong&gt; bcrypt, scrypt, or Argon2. Never SHA-256, never MD5, never plaintext.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep tokens out of local storage.&lt;/strong&gt; Any script on the page can read &lt;code&gt;localStorage&lt;/code&gt;. Session tokens belong in httpOnly, Secure, SameSite cookies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-side API secrets.&lt;/strong&gt; No keys in client code. Check your &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; and &lt;code&gt;VITE_&lt;/code&gt; variables specifically, because those prefixes mean "bundle this into the JavaScript that ships to every visitor." A &lt;code&gt;service_role&lt;/code&gt; key in client code bypasses every RLS policy you wrote.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parameterized SQL queries.&lt;/strong&gt; Never concatenate user input into a query.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate form inputs.&lt;/strong&gt; Server-side, with a schema. Client-side validation is a UX feature, not a security control.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Block cross-site scripting.&lt;/strong&gt; Escape output, avoid &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt; with untrusted content, set a Content-Security-Policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate file uploads.&lt;/strong&gt; Check type and size, and never trust the filename. Don't serve uploads from the same origin as your app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify webhook signatures.&lt;/strong&gt; An unverified webhook endpoint accepts forged events from anyone who guesses the URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rate limit requests.&lt;/strong&gt; Login, signup, password reset, and anything that sends email or costs money.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tighten CORS settings.&lt;/strong&gt; No wildcard origins on authenticated endpoints. Origin reflection with credentials enabled means any website can make authenticated requests on a logged-in user's behalf.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Disable production debugging.&lt;/strong&gt; Debug endpoints, verbose stack traces, GraphQL introspection, and source maps should all be off.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update dependencies.&lt;/strong&gt; Run the audit, fix what it flags.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run an actual security review.&lt;/strong&gt; Anthropic open-sourced &lt;code&gt;claude-code-security-review&lt;/code&gt; under MIT. It's a GitHub Action that comments findings on your PRs, and Claude Code ships a &lt;code&gt;/security-review&lt;/code&gt; slash command that does the same analysis. One caveat worth knowing: the action is not hardened against prompt injection, and Anthropic's own README says to use it only on trusted PRs. Set your repo to "require approval for all external contributors" first.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Two things people get wrong
&lt;/h2&gt;

&lt;p&gt;The checklist is worth nothing if you skip these.&lt;/p&gt;

&lt;p&gt;Confirm your &lt;code&gt;.env&lt;/code&gt; files are actually excluded from Git, not just that they should be. Run &lt;code&gt;git check-ignore .env&lt;/code&gt; and make sure it returns a match. If a secret ever reached a commit, rotating it is the only real fix. Rewriting history is cleanup, not a cure.&lt;/p&gt;

&lt;p&gt;Then confirm sensitive data stays out of your logs. Logs get shipped, aggregated, and read by more people than you think. Never log tokens, passwords, full request bodies, or PII. Check your error handlers specifically, because that's where request objects get dumped wholesale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves you
&lt;/h2&gt;

&lt;p&gt;Your app probably works. That's the part AI genuinely got good at. The security defaults underneath it are a different story, and the pattern across thousands of scanned apps says most of them haven't been touched.&lt;/p&gt;

&lt;p&gt;None of this is expensive or exotic to fix. RLS is a policy on a table. Keeping a key server-side is moving a file. A CSP header is a config line. A large share of the exposures found in these scans were one default away from not existing.&lt;/p&gt;

&lt;p&gt;Go check your tables. Start with the ones holding user data.&lt;/p&gt;

</description>
      <category>security</category>
      <category>supabase</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Billions of Log Rows, One Command to Make Them Disappear</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 20 Sep 2026 10:07:56 +0000</pubDate>
      <link>https://dev.to/chizee/billions-of-log-rows-one-command-to-make-them-disappear-1pa4</link>
      <guid>https://dev.to/chizee/billions-of-log-rows-one-command-to-make-them-disappear-1pa4</guid>
      <description>&lt;p&gt;Telemetry and event logs only grow. Dump them into one giant table and every query — even one scoped to a single day — ends up scanning far more data than it needs to. That's usually the exact moment a team reaches for a dedicated time-series database like InfluxDB.&lt;/p&gt;

&lt;p&gt;Two native Postgres features cover most of what people reach for InfluxDB to get: declarative partitioning and BRIN indexes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Split the table without splitting the app
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="n"&gt;bigserial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;event_time&lt;/span&gt;  &lt;span class="n"&gt;timestamptz&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt;     &lt;span class="n"&gt;jsonb&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;RANGE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;events_2026_06&lt;/span&gt; &lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;OF&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;
  &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2026-06-01'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2026-07-01'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One note that will save you a confusing error: &lt;code&gt;id&lt;/code&gt; is deliberately not a primary key here. On a partitioned table, any unique or primary key constraint has to include the partition column. If you need one, it's &lt;code&gt;PRIMARY KEY (id, event_time)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A featherweight index built for this exact shape of data
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_events_time_brin&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;BRIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;BRIN&lt;/code&gt; (Block Range Index) stores just the minimum and maximum value for each physical block of disk, instead of indexing every single row the way a B-Tree does. For data that arrives roughly in time order — which almost all event data does — that's enough to skip millions of irrelevant pages instantly, at a fraction of a B-Tree's size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;event_time&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt; &lt;span class="s1"&gt;'2026-06-10'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="s1"&gt;'2026-06-11'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;EXPLAIN&lt;/code&gt; on that and you'll see the planner only touches the one relevant partition — the rest are pruned before the query even runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retention becomes a metadata operation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;events_2026_06&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No &lt;code&gt;DELETE&lt;/code&gt; scan, no bloat left behind to vacuum. Dropping a partition removes its rows instantly — I tested this directly: 500 seeded rows, one &lt;code&gt;DROP TABLE&lt;/code&gt;, zero rows left, no measurable delay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats a dedicated time-series database
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Retention policies are a &lt;code&gt;DROP TABLE&lt;/code&gt;, not a scheduled bulk delete job.&lt;/li&gt;
&lt;li&gt;BRIN indexes cost a sliver of what an equivalent B-Tree would.&lt;/li&gt;
&lt;li&gt;It's the same SQL as the rest of your schema — no separate query language, no separate client library.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where InfluxDB still wins
&lt;/h2&gt;

&lt;p&gt;Purpose-built downsampling and retention policies out of the box, at ingest rates in the millions of points per second. If you're managing your own partitions and indexes comfortably below that, you're not missing anything by staying on Postgres.&lt;/p&gt;




&lt;p&gt;This is one of eight infrastructure swaps in &lt;strong&gt;Just Use Postgres&lt;/strong&gt;, a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance before it went in the book.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Get the field manual&lt;/strong&gt; — launch price &lt;strong&gt;$14&lt;/strong&gt; instead of scanning a billion-row table for yesterday's data: &lt;a href="https://payhip.com/omenabyte" rel="noopener noreferrer"&gt;https://payhip.com/omenabyte&lt;/a&gt;&lt;br&gt;
🐳 Or take the &lt;strong&gt;$24 bundle&lt;/strong&gt; with the full &lt;code&gt;docker-compose up&lt;/code&gt; starter repo — all 8 modules as tested, runnable migrations + seed data: &lt;a href="https://4693433176360.gumroad.com/" rel="noopener noreferrer"&gt;https://4693433176360.gumroad.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Read this on omenabyte.com → &lt;a href="https://omenabyte.com/blog/replace-influxdb-with-partitioning-brin" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-influxdb-with-partitioning-brin&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>timeseries</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>You Don't Need MongoDB for "Flexible" Data. You Need One Column Type.</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 06 Sep 2026 10:14:11 +0000</pubDate>
      <link>https://dev.to/chizee/you-dont-need-mongodb-for-flexible-data-you-need-one-column-type-35c1</link>
      <guid>https://dev.to/chizee/you-dont-need-mongodb-for-flexible-data-you-need-one-column-type-35c1</guid>
      <description>&lt;p&gt;Product catalogs, form submissions, webhook payloads — a lot of real data genuinely doesn't want a fixed schema. The usual response is reaching for MongoDB purely for that flexibility, which means a second connection pool, a second backup strategy, and a second place your data can quietly drift out of sync with the relational tables that still describe your users and orders.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jsonb&lt;/code&gt; solves the actual problem — flexible structure — without giving up the database you already trust for everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store anything
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="n"&gt;bigserial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;        &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;attributes&lt;/span&gt;  &lt;span class="n"&gt;jsonb&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_products_attributes&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;jsonb&lt;/code&gt;, not &lt;code&gt;json&lt;/code&gt;. The binary form is stored decomposed at write time instead of as text re-parsed on every read — that's the difference between something you can actually index and something you can only display.&lt;/p&gt;

&lt;h2&gt;
  
  
  Query it like you mean it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt; &lt;span class="o"&gt;@&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{"color": "red", "size": "M"}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GIN index makes this fast the same way a book's index works: it maps individual keys and values straight to the rows that contain them, instead of scanning every row to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part MongoDB genuinely can't do as cleanly
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_date&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;order_items&lt;/span&gt; &lt;span class="n"&gt;oi&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;oi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'specs'&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'material'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'leather'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a document-style attribute joined directly against relational order history, in one statement, inside one transaction. Try that across two databases and you're writing application-layer stitching code — and hoping nothing changes between the two calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats standing up a document database
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One transaction, not two systems — the "document" and the relational rows referencing it commit or roll back together.&lt;/li&gt;
&lt;li&gt;No sync jobs, because there's no second database to keep consistent.&lt;/li&gt;
&lt;li&gt;You can still join it, which is the thing you actually lose by going full-document.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where MongoDB still wins
&lt;/h2&gt;

&lt;p&gt;Genuinely schema-less workloads at a write scale where horizontal partitioning across many nodes is a day-one requirement, or built-in multi-region active-active replication out of the box. Most projects reaching for Mongo on day one aren't actually at that scale yet.&lt;/p&gt;




&lt;p&gt;This is one of eight infrastructure swaps in &lt;strong&gt;Just Use Postgres&lt;/strong&gt;, a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance before it went in the book.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Get the field manual&lt;/strong&gt; — launch price &lt;strong&gt;$14&lt;/strong&gt; instead of multiplying connection pools, backup jobs, and consistency headaches: &lt;a href="https://payhip.com/omenabyte" rel="noopener noreferrer"&gt;https://payhip.com/omenabyte&lt;/a&gt;&lt;br&gt;
🐳 Or take the &lt;strong&gt;$24 bundle&lt;/strong&gt; with the full &lt;code&gt;docker-compose up&lt;/code&gt; starter repo — all 8 modules as tested, runnable migrations + seed data: &lt;a href="https://4693433176360.gumroad.com/" rel="noopener noreferrer"&gt;https://4693433176360.gumroad.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Read this on omenabyte.com → &lt;a href="https://omenabyte.com/blog/replace-mongodb-with-jsonb" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-mongodb-with-jsonb&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>mongodb</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Your AI Feature Doesn't Need Pinecone. It Needs pgvector.</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 30 Aug 2026 22:50:42 +0000</pubDate>
      <link>https://dev.to/chizee/your-ai-feature-doesnt-need-pinecone-it-needs-pgvector-4e5k</link>
      <guid>https://dev.to/chizee/your-ai-feature-doesnt-need-pinecone-it-needs-pgvector-4e5k</guid>
      <description>&lt;h1&gt;
  
  
  Launch Workspace — "Just Use Postgres" Week 3 (Article 3 / Week 4)
&lt;/h1&gt;

&lt;p&gt;Dev.to title: Your AI Feature Doesn't Need Pinecone. It Needs pgvector.&lt;br&gt;
Slug: /blog/replace-pinecone-with-pgvector&lt;br&gt;
Canonical URL: &lt;a href="https://omenabyte.com/blog/replace-pinecone-with-pgvector" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-pinecone-with-pgvector&lt;/a&gt;&lt;br&gt;
dev.to tags: postgres, ai, vectordatabase, tutorial&lt;br&gt;
Cover: &lt;a href="https://omenabyte.com/blog/just-use-postgres-cover.png" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/just-use-postgres-cover.png&lt;/a&gt;&lt;br&gt;
Series: The Field Manual Series&lt;br&gt;
Medium topics: &lt;code&gt;PostgreSQL, Databases, SQL, Web Development, Software Engineering&lt;/code&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Your AI Feature Doesn't Need Pinecone. It Needs pgvector.
&lt;/h1&gt;

&lt;p&gt;The moment a project needs semantic search or RAG, the instinct is to bolt on a dedicated vector database. It works fine right up until you need a semantic match &lt;em&gt;and&lt;/em&gt; a relational filter at the same time — "find documents like this one, but only ones this specific user wrote" — and now you're querying two separate systems and stitching results back together over a network call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pgvector&lt;/code&gt; puts the embedding in the same row as everything else about the thing it describes, so that query is just... a query.&lt;/p&gt;
&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="n"&gt;bigserial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;author_id&lt;/span&gt;   &lt;span class="nb"&gt;bigint&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt;     &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;embedding&lt;/span&gt;   &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_documents_embedding&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;hnsw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;vector_cosine_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;HNSW&lt;/code&gt; (Hierarchical Navigable Small World) builds a multi-layered graph over your vectors — think of it as a high-dimensional skip list — so approximate nearest-neighbor search stays fast as the table grows.&lt;/p&gt;
&lt;h2&gt;
  
  
  The query that used to need two databases
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;author_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'[0.012, -0.045, 0.031, ...]'&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Semantic ranking and a relational filter, one round trip, one transaction, one system to keep consistent.&lt;/p&gt;
&lt;h2&gt;
  
  
  The gotcha nobody mentions
&lt;/h2&gt;

&lt;p&gt;Here's something worth knowing before you ship this: with an approximate index like HNSW, Postgres fetches the nearest candidates &lt;em&gt;first&lt;/em&gt;, then applies the &lt;code&gt;WHERE&lt;/code&gt; clause &lt;em&gt;after&lt;/em&gt;. If &lt;code&gt;author_id = 42&lt;/code&gt; is a narrow slice of a large table, you can get back fewer than 5 rows — not an error, just a quietly short result.&lt;/p&gt;

&lt;p&gt;The fix, if you're on pgvector 0.8 or newer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;hnsw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iterative_scan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'strict_order'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps scanning until the filter is actually satisfied instead of settling for whatever the first pass turned up. Worth checking your version — &lt;code&gt;SELECT extversion FROM pg_extension WHERE extname = 'vector';&lt;/code&gt; — since some package managers (looking at you, plain &lt;code&gt;apt&lt;/code&gt;) ship versions old enough not to have this option yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats a dedicated vector database for most teams
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Embeddings and the rows they describe are written in the same transaction — they can never drift out of sync.&lt;/li&gt;
&lt;li&gt;Hybrid search (semantic + relational) is a single query instead of an application-layer join.&lt;/li&gt;
&lt;li&gt;One fewer vendor, one fewer bill.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Pinecone still wins
&lt;/h2&gt;

&lt;p&gt;Billion-vector scale, with dedicated horizontally-sharded ANN infrastructure and managed elastic scaling. If you're not there yet, you're paying for infrastructure you don't need.&lt;/p&gt;




&lt;p&gt;This is one of eight infrastructure swaps in &lt;strong&gt;Just Use Postgres&lt;/strong&gt;, a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance with &lt;code&gt;pgvector&lt;/code&gt; before it went in the book.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://payhip.com/omenabyte" rel="noopener noreferrer"&gt;Get the field manual&lt;/a&gt; — launch price &lt;strong&gt;$14&lt;/strong&gt; instead of walking into a $50/month managed-vector invoice&lt;/p&gt;

&lt;p&gt;🐳 Or take the &lt;strong&gt;$24 bundle&lt;/strong&gt; with the full &lt;code&gt;docker-compose up&lt;/code&gt; starter repo — all 8 modules as tested, runnable migrations + seed data: &lt;a href="https://4693433176360.gumroad.com/" rel="noopener noreferrer"&gt;https://4693433176360.gumroad.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Read this on omenabyte.com → &lt;a href="https://omenabyte.com/blog/replace-pinecone-with-pgvector" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-pinecone-with-pgvector&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>ai</category>
      <category>vectordatabase</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Watched a Man's Certainty Evaporate in Real Time</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 30 Aug 2026 09:51:37 +0000</pubDate>
      <link>https://dev.to/chizee/i-watched-a-mans-certainty-evaporate-in-real-time-4lm3</link>
      <guid>https://dev.to/chizee/i-watched-a-mans-certainty-evaporate-in-real-time-4lm3</guid>
      <description>&lt;h2&gt;
  
  
  The most dangerous hacker in the room never touched a keyboard.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Or: why "I use strong passwords" is the least effective security strategy you own.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;There's a story we tell ourselves about security. It goes like this: &lt;em&gt;as long as I use strong, unique passwords, enable two-factor authentication, and never click on anything even slightly suspicious, I'm one of the safe ones.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I told myself that story for years. Then I watched a woman break it apart in real time — through a screen, on someone else's podcast — and it rattled me more than I expected it to.&lt;/p&gt;

&lt;p&gt;The man in the hot seat ran a security-focused YouTube channel and podcast. He'd built his entire platform on exposing scammers and teaching everyday people how to outsmart them. Two-factor authentication? On. Passwords? Long, random, different on every damn site. Sketchy links? Never touched them. By every checklist the internet had ever handed him, he was bulletproof.&lt;/p&gt;

&lt;p&gt;He sat down across from &lt;strong&gt;Rachel Tobac&lt;/strong&gt; — CEO of Social Proof Security, one of the best social engineers on the planet — and offered her a challenge: &lt;em&gt;research me. Try to break me.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A few sentences later, the smug was gone.&lt;/p&gt;

&lt;p&gt;She said his &lt;strong&gt;full legal name&lt;/strong&gt; — bleeped for the audio, the name he'd gone out of his way for years to never use publicly. Then she told him where he was from. Then she named the city. Then she started pulling out the strange, buried details of an old life — a competitive program he'd almost forgotten, a hobby he'd packed away years ago, even an &lt;em&gt;America's Got Talent&lt;/em&gt; audition that never made it to air.&lt;/p&gt;

&lt;p&gt;He stopped looking her in the eye. His hands went cold.&lt;/p&gt;

&lt;p&gt;She hadn't hacked his computer. She hadn't cracked a single password. She hadn't touched a single line of code. She had done something far more dangerous: &lt;strong&gt;she had hacked him.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The uncomfortable truth: you're the weakest link
&lt;/h2&gt;

&lt;p&gt;Social engineering isn't hacking computers. It's hacking the operating system that runs them: &lt;em&gt;you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And here's what decades of data breaches, security research, and live demonstrations keep proving — the strongest technical defense in the world becomes meaningless the moment a stranger can convince a human being to open the door:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Everyone can be hacked except you. You've got two-factor authentication turned on. All of your passwords are super strong. … But you're still not safe from this person." — Rachel Tobac&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The attacks that actually work aren't glamorous. They don't involve servers or exploit chains. They're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A 30-second phone call.&lt;/strong&gt; Rachel's first professional engagement: she called an executive's assistant, pretended to be from finance, and got everything she needed — the kind of information that could move company money — in &lt;em&gt;thirty seconds&lt;/em&gt;. She didn't attack the gatekeeper's boss. She attacked the person whose job is to be agreeable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MFA fatigue.&lt;/strong&gt; Attackers don't break your two-factor authentication. They &lt;em&gt;spam&lt;/em&gt; it — push notification after push notification at 11pm, until you're tired and annoyed and just want it to stop. Then you hit &lt;em&gt;accept&lt;/em&gt;, and the game is over. Around half of people admit to reusing passwords (Google's survey), which is what makes the spam worth sending.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caller ID that lies.&lt;/strong&gt; Your phone displays a name and photo for numbers in your contacts. Attackers can make a call &lt;em&gt;display&lt;/em&gt; as if it's from your bank — or your mom. In the interview, Rachel did something she'd never done on air: she called the host live, by phone, in front of his co-host and millions of listeners. He &lt;em&gt;knew&lt;/em&gt; it was happening, in real time, and still almost went for it. His words afterward: &lt;strong&gt;"I'm still reeling from that."&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scariest part isn't that an expert got caught. It's that he wasn't special. The words that broke him would work on almost anyone in that room.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 10 rules of being politely paranoid
&lt;/h2&gt;

&lt;p&gt;The good news: if the game is two steps — &lt;em&gt;build rapport, make a plausible ask&lt;/em&gt; — then the defense can be taught in two steps too. When Rachel was asked for her final advice, she gave a phrase that's worth writing on a sticky note:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Be politely paranoid — because the information that's out there for almost every person on the internet can be used to trick you, or the people around you."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are the ten rules distilled from that conversation. Screenshot this. Read it twice. Then teach it to your parents — scammers target them through their own kindness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Alerts you didn't start are always suspicious.&lt;/strong&gt; If a login push arrives and you didn't just log in — that's your first red flag. Don't accept, don't deny, don't trust anyone on the phone who insists you do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Verify through a second channel — always.&lt;/strong&gt; Anyone asking you to move money, reset access, or share a code gets one response: a fresh conversation on a channel &lt;em&gt;you&lt;/em&gt; control. Call the number on the back of your card. A real request survives the check. A scam never does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Slow down the moment someone creates urgency.&lt;/strong&gt; "It has to be now" is a script, not a fact. Real systems don't panic you. Scammers do. Your superpower is refusing to rush.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Treat caller ID as a suggestion, not proof.&lt;/strong&gt; Numbers and contact cards can be faked. If a call looks like your bank and starts asking for anything — verify on a number you dialed yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. One unique password per account.&lt;/strong&gt; A breach at some forgotten 2016 site should cost you exactly one account — never the keys to your bank, your email, and your work. A password manager makes this painless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. MFA on, but never MFA by panic.&lt;/strong&gt; Keep two-factor authentication everywhere. Just remember its one weakness: the accept button. Treat every prompt you didn't start as suspicious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Be stingy with your face and your ID.&lt;/strong&gt; You can rotate a password. You can cancel a card. &lt;strong&gt;You cannot change your face.&lt;/strong&gt; Hand out biometrics and government ID as if they were the last copies on earth — because they effectively are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Treat AI output like a stranger on the phone.&lt;/strong&gt; Plausible doesn't mean true. Rachel has documented cases where AI &lt;em&gt;reinforced&lt;/em&gt; people's delusions instead of correcting them — an agreeable machine that never tells you you're wrong. Verify anything important it tells you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Be the wall for people around you.&lt;/strong&gt; Scammers target your family and colleagues through their own kindness. Be the person who gently asks, &lt;em&gt;"wait — did you actually ask for this?"&lt;/em&gt; before someone loses years of savings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. Keep playing whack-a-mole.&lt;/strong&gt; Security is a habit, not a finish line. New scams will keep arriving. Don't tune out — spot the current one, defend, teach, move on. That's the whole game, and you can win it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the machines make it worse (and better)
&lt;/h2&gt;

&lt;p&gt;Rachel's warnings about AI are the most urgent part of the conversation. There's a real case of a well-known venture capitalist who spiraled into a false belief system — convinced he was being tracked by a shadowy organization — because the LLM he talked to validated his delusions, drawing on science fiction in its training data and presenting it as fact. No attacker involved. The danger was the tool itself: an agreeable machine that could not tell him he was wrong.&lt;/p&gt;

&lt;p&gt;But there's a counterweight. The same technology that writes a perfect phishing email can catch the worst content on the internet so no human has to look at it. Rachel once interviewed for a job moderating content for a major social platform — the interviewer asked how comfortable she'd be seeing pictures of, say, &lt;em&gt;children in cages&lt;/em&gt;. She didn't get the job, and she's glad. Some jobs are too horrible for humans, and those are the jobs the machines should do.&lt;/p&gt;

&lt;p&gt;The honest forecast for AI security is roughly 50/50 — a perpetual whack-a-mole between offense and defense. The side that wins is the side that stays sharp.&lt;/p&gt;




&lt;h2&gt;
  
  
  The strongest password you'll ever have
&lt;/h2&gt;

&lt;p&gt;Here's the line that closed the conversation, and it's worth sitting with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The strongest password you'll ever have is the refusal to believe the last person who asked.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The scammers are praying you don't know what scams look like. They bank on urgency, pressure, and a phone number that looks exactly right. When you're politely paranoid — warm, human, but unwilling to act on urgency alone — you catch them every time.&lt;/p&gt;

&lt;p&gt;I went so deep into this conversation — the 30-second hack, the MFA fatigue game, the live call, the AI psychosis cases, and the full defense playbook — that I turned it into a book. It's called &lt;strong&gt;Be Politely Paranoid&lt;/strong&gt;, and it's the complete, chapter-by-chapter breakdown of how social engineers think and how to build your human firewall.&lt;/p&gt;

&lt;p&gt;If this post resonated, the book goes deeper — every attack dissected, every defense explained, and the full 10-rule playbook you can print and stick on your wall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://4693433176360.gumroad.com/l/be-politely-paranoid" rel="noopener noreferrer"&gt;Get &lt;em&gt;Be Politely Paranoid&lt;/em&gt; here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It's the cheapest security upgrade you'll ever buy — and it protects the people you love, not just your accounts.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is an independent commentary on a publicly available interview. It is not authorized, endorsed, or reviewed by Rachel Tobac or Social Proof Security. Quotes have been lightly edited for readability.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>socialeng</category>
      <category>infosec</category>
    </item>
    <item>
      <title>The Prompting Gap Is the Only Gap Left</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 30 Aug 2026 09:51:24 +0000</pubDate>
      <link>https://dev.to/chizee/the-prompting-gap-is-the-only-gap-left-p72</link>
      <guid>https://dev.to/chizee/the-prompting-gap-is-the-only-gap-left-p72</guid>
      <description>&lt;p&gt;There's an uncomfortable pattern I keep seeing.&lt;/p&gt;

&lt;p&gt;Two developers, same repo, same version of Claude Code, same task. One of&lt;br&gt;
them is done in ten minutes — tests written, PR open, moving on. The&lt;br&gt;
other is twenty minutes deep in a back-and-forth, re-explaining context&lt;br&gt;
Claude should've already had, watching it guess at requirements nobody&lt;br&gt;
stated.&lt;/p&gt;

&lt;p&gt;Same tool. Wildly different outcomes.&lt;/p&gt;

&lt;p&gt;It's not a skill gap. It's not even an experience gap. It's a&lt;br&gt;
&lt;strong&gt;vocabulary gap&lt;/strong&gt; — and it's the last one standing between "I have an AI&lt;br&gt;
coding assistant" and "I ship noticeably faster than I did six months&lt;br&gt;
ago."&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool got good before the instructions did
&lt;/h2&gt;

&lt;p&gt;Claude Code can trace a bug from a vague symptom to a root cause. It can&lt;br&gt;
read a Terraform plan and tell you what's about to break. It can turn a&lt;br&gt;
CSV of ad performance into twenty new headline variations that fit under&lt;br&gt;
a character limit. It can do a &lt;em&gt;lot&lt;/em&gt; of things most people never ask it&lt;br&gt;
to do — because most people never think to ask.&lt;/p&gt;

&lt;p&gt;Anthropic has actually published a lot of this — scattered across a&lt;br&gt;
Common Workflows guide, a best-practices doc, a "how our own teams use&lt;br&gt;
Claude Code" writeup, and a few deep dives into how their legal and&lt;br&gt;
security teams use it internally. Genuinely great material. Also,&lt;br&gt;
genuinely annoying to piece together from six different pages when&lt;br&gt;
you're mid-task and just want to know what to type.&lt;/p&gt;

&lt;p&gt;So I pulled all 52 prompts into one place, organized them the way you&lt;br&gt;
actually work — not alphabetically, not by topic, but by &lt;em&gt;where you are&lt;br&gt;
in the process&lt;/em&gt; — and turned it into a field guide. More on that below.&lt;br&gt;
First, the part that actually matters more than any single prompt:&lt;/p&gt;

&lt;h2&gt;
  
  
  Six patterns, not fifty-two prompts
&lt;/h2&gt;

&lt;p&gt;Here's the thing nobody tells you about "good" prompts: memorizing&lt;br&gt;
someone else's exact wording only gets you so far. What's actually&lt;br&gt;
transferable are the &lt;em&gt;patterns&lt;/em&gt; underneath them. Learn these six and you&lt;br&gt;
can write your own prompt for a problem no cheat sheet ever anticipated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Describe the outcome, not the steps.&lt;/strong&gt;&lt;br&gt;
Say what you want and let Claude find the files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;add rate limiting to the public API and make sure existing tests still pass&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Give it a way to check its own work.&lt;/strong&gt;&lt;br&gt;
Ask for run, test, compare, or verify in the same breath so it iterates&lt;br&gt;
instead of stopping after one guess.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;write the migration, run it against the dev database, and confirm the schema matches&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3. Point at a reference.&lt;/strong&gt;&lt;br&gt;
Name an existing file or pattern to match. Without one, Claude defaults&lt;br&gt;
to generic best practices. With one, it matches &lt;em&gt;your&lt;/em&gt; conventions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;add a settings page that follows the same layout as the profile page&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. State the measurable target.&lt;/strong&gt;&lt;br&gt;
When the goal is performance or coverage, give the number. Ambiguous&lt;br&gt;
goals get ambiguous effort.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;get the bundle size under 200KB and show me what you removed&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;5. Give it the artifact.&lt;/strong&gt;&lt;br&gt;
Paste the error, the log, the screenshot, the plan output. Don't&lt;br&gt;
describe the problem — hand over the evidence.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;why is the build failing? @build.log&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;6. Say how you want the answer.&lt;/strong&gt;&lt;br&gt;
Name the format, the length, the audience. "Explain this" and "explain&lt;br&gt;
this as a diagram I can show a PM" are two different prompts with two&lt;br&gt;
different amounts of usefulness.&lt;/p&gt;

&lt;p&gt;Once these six patterns click, you stop needing a cheat sheet for&lt;br&gt;
&lt;em&gt;everything&lt;/em&gt;. You just need one for the stuff you don't do often enough&lt;br&gt;
to have memorized — which is exactly what the rest of this is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few, to prove it's not just theory
&lt;/h2&gt;

&lt;p&gt;One from each stage, straight out of the library:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting oriented in a repo you've never seen:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;give me an overview of this codebase: architecture, key directories, and how the pieces connect&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Scoping a change before you promise a timeline:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;which files would I need to touch to add a dark mode toggle to settings?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Catching a risky change before you commit it:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;review my uncommitted changes and flag anything that looks risky before I commit&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Investigating an incident without five browser tabs open:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;the checkout endpoint started returning 500s an hour ago. check the logs, recent deploys, and config changes, then tell me the most likely cause&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Turning a one-off fix into something your whole team benefits from:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;you keep using default exports when this project uses named exports. add a rule to CLAUDE.md so this stops happening&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;None of these are clever. That's the point. The unlock isn't cleverness —&lt;br&gt;
it's specificity, evidence, and knowing what to ask for at each stage of&lt;br&gt;
the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the full library
&lt;/h2&gt;

&lt;p&gt;52 prompts across five stages — &lt;strong&gt;Discover, Design, Build, Ship,&lt;br&gt;
Operate&lt;/strong&gt; — each with the exact wording, the technique it teaches, role&lt;br&gt;
tags for PM/Design/Marketing/Docs/Security/Ops/Data (this isn't just an&lt;br&gt;
engineering cheat sheet), and a "try next" tip for turning a good prompt&lt;br&gt;
into a standing team habit instead of something you type from memory&lt;br&gt;
every time.&lt;/p&gt;

&lt;p&gt;23 pages. One download. Every prompt copy-paste ready.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://4693433176360.gumroad.com/l/ThePromptLibrary" rel="noopener noreferrer"&gt;Get The Prompt Library →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;— Omenabyte Intelligence&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>1027 AI Image Slash Commands That Will 10x Your Prompt Game</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 30 Aug 2026 09:47:28 +0000</pubDate>
      <link>https://dev.to/chizee/1027-ai-image-slash-commands-that-will-10x-your-prompt-game-4ma6</link>
      <guid>https://dev.to/chizee/1027-ai-image-slash-commands-that-will-10x-your-prompt-game-4ma6</guid>
      <description>&lt;h2&gt;
  
  
  The &lt;code&gt;/imagine&lt;/code&gt; trick that started a thousand cheat sheets
&lt;/h2&gt;




&lt;p&gt;&lt;strong&gt;The secret nobody talks about:&lt;/strong&gt; the most powerful image prompts aren't paragraphs. They're not even single sentences.&lt;/p&gt;

&lt;p&gt;They're &lt;strong&gt;slash commands&lt;/strong&gt; — shorthand modifiers you chain together like building blocks.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/portrait /1980s /bokeh /ar-3-4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's a complete, professional image prompt in five seconds. And it works across Midjourney, DALL-E 3, Leonardo.ai, SDXL, Flux, and ChatGPT.&lt;/p&gt;

&lt;p&gt;Here's how this shorthand revolution started — and why you should care.&lt;/p&gt;




&lt;h2&gt;
  
  
  The birth of &lt;code&gt;/imagine&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In March 2022, Midjourney opened its Beta to the public. Everyone got the same first instruction: type &lt;code&gt;/imagine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not a long prompt. Not a style guide. Just one slash and a word.&lt;/p&gt;

&lt;p&gt;Within weeks, Discord servers were exploding with people sharing their &lt;code&gt;/imagine&lt;/code&gt; prompts — and a pattern emerged. The most prolific generators weren't writing paragraphs. They were dropping a few keywords, a style, a camera modifier. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/imagine prompt: a woman made of smoke / cyberpunk / neon / cinematic lighting / ar 16:9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not a sentence. It's a &lt;strong&gt;command sequence&lt;/strong&gt;. And it was faster than English.&lt;/p&gt;

&lt;p&gt;Fast-forward to 2026. The &lt;code&gt;/slash&lt;/code&gt; convention has gone multi-platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ChatGPT&lt;/strong&gt; image gen uses &lt;code&gt;/imagine&lt;/code&gt; (inherited from Midjourney muscle memory)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leonardo.ai&lt;/strong&gt; supports &lt;code&gt;/model&lt;/code&gt;, &lt;code&gt;/style&lt;/code&gt;, &lt;code&gt;/ar&lt;/code&gt; shorthand&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable Diffusion&lt;/strong&gt; web UIs use &lt;code&gt;/ar&lt;/code&gt;, &lt;code&gt;/q&lt;/code&gt;, &lt;code&gt;/sameseed&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DALL-E&lt;/strong&gt; doesn't natively use slashes but follows the same compositional pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each platform has 50–200 native modifiers. Combined? 500–1000+ composable commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why slash commands beat full prompts (most of the time)
&lt;/h2&gt;

&lt;p&gt;There's a trade-off every image generator runs into:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Full Prompt&lt;/th&gt;
&lt;th&gt;Slash Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;✍️ Write a paragraph&lt;/td&gt;
&lt;td&gt;✅ Drop a code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📱 Copy-paste is fragile&lt;/td&gt;
&lt;td&gt;💾 Save and reuse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔄 Hard to edit&lt;/td&gt;
&lt;td&gt;🔗 Combine freely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❓ 800 tokens&lt;/td&gt;
&lt;td&gt;🔢 5 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Slash commands are &lt;strong&gt;deterministic shortcuts&lt;/strong&gt;. You learn them like muscle memory — type &lt;code&gt;/cyberpunk /neon /ar-16-9&lt;/code&gt; and you know what you'll get before the image even renders.&lt;/p&gt;

&lt;p&gt;The sweet spot: &lt;strong&gt;build a library of 20–30 core commands&lt;/strong&gt; you know by heart, then chain them per project. That's what this 1027-command handbook distills.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 5 categories you'll use 80% of the time
&lt;/h2&gt;

&lt;p&gt;Not all 1027 commands are equal. Based on analyzing which ones ship most often:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 📐 Foundation Modifiers (30 commands)
&lt;/h3&gt;

&lt;p&gt;These control the basics — the "what format" question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ar-16-9     → 16:9 (YouTube thumbnail)
/ar-1-1      → 1:1 (Instagram square)
/quality-high → 2x GPU / max detail
/stylize-medium → balanced artistic flair
/no-text     → bans text in output
/seed-pin    → reproducible seed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 🔦 Perspective / Camera (30 commands)
&lt;/h3&gt;

&lt;p&gt;The "from where" question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/lowangle   → low camera angle
/overhead  → top-down
/birdseye   → looking straight down
/pov        → first-person point of view
/ultra-wide → fish-eye wide angle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 🎨 Style &amp;amp; Medium (30 commands)
&lt;/h3&gt;

&lt;p&gt;The "how does it look" question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/photoreal   → photo realism
/oilpainting → oil on canvas
/cyberpunk   → neon-drenched sci-fi
/lowpoly    → geometric faceted look
/glitch-art  → digital corruption aesthetic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. 💡 Lighting (26 commands)
&lt;/h3&gt;

&lt;p&gt;The "mood" question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goldenhour  → warm evening light
/neonlight    → neon tubes/glow
/volumetric   → visible light rays
/ring-light   → creator/streamer setup
/lowkey       → high contrast shadows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. 📱 Output Format (20 commands)
&lt;/h3&gt;

&lt;p&gt;Where it lives — the "what shape" question.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/youtube-thumbnail → 1280×720 ready
/tiktok-cover      → 9:16 mobile
/poster            → 3:4 tall poster
/book-cover         → 2:3 A4-ish
/banner             → 16:7 wide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Master these 136 commands, and you can compose ~8,000 valid combinations without ever writing a full-sentence prompt.&lt;/p&gt;




&lt;h2&gt;
  
  
  Advanced: chaining for complex results
&lt;/h2&gt;

&lt;p&gt;Here's where slash commands get dangerous. You're not limited to one per category:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/imagine: a lone astronaut / cyberpunk / neon / lowangle / goldenhour / rain / motionblur / ar-9-16 / no-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's &lt;strong&gt;one&lt;/strong&gt; command chain producing a cinematic, specific, ready-to-post image. The astronaut is a modifier — it slots into any scene chain.&lt;/p&gt;

&lt;p&gt;Power users chain &lt;strong&gt;3 foundation + 3 style + 2 perspective + 1 lighting&lt;/strong&gt; + output = 9 commands. That's more creative precision than a 100-word paragraph, and infinitely more editable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's in the full handbook
&lt;/h2&gt;

&lt;p&gt;I didn't stop at the 136 power commands. The complete handbook covers all &lt;strong&gt;1027 commands&lt;/strong&gt; across &lt;strong&gt;28 categories&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🎯  Foundation         (aspect, quality, model, seed)
📐  Technical          (CAD, blueprint, exploded view, cutaway)
🧪  Science/Medical    (DNA, anatomy, microscope, MRI)
📊  Infographics      (charts, flowcharts, dashboards)
📦  Product           (product shots, packshots, unboxing)
📣  Advertising         (ads for Meta, Google, billboards)
📱  Social Media       (IG, TikTok, YouTube, LinkedIn)
📸  Photography         (film stocks, lenses, bokeh)
🎬  Cinematic           (movie posters, noir, steampunk)
🌅  Lighting            (golden hour, neon, rim light)
🌍  Camera Angles       (drone, bird's eye, Dutch tilt)
🎨  Art Styles          (oil, manga, pixel art, stained glass)
🧊  3D/CGI              (Blender, Octane, ray tracing)
🏢  Architecture         (floor plans, modern, brutalist)
👤  People/Fashion       (headshots, runway, vintage)
🏎️  Vehicles/Machines    (cars, rockets, aircraft)
🧠  Concept/Creative      (cyberpunk, dystopian, surreal)
🏷️  Branding/Design        (logos, posters, style guides)
🖼️  Image Editing         (restore, inpaint, sky replace)
🗺️  Maps/Travel            (topographic, fantasy, metro maps)
🕰️  Historical/Vintage     (decade styles, daguerreotype)
🎨  Colors &amp;amp; Palettes      (duotone, neon, earth tones)
🧱  Textures &amp;amp; Materials   (concrete, marble, holographic)
🌿  Nature/Elements        (forest, storm, aurora)
🦁  Animals/Creatures       (wildlife, dragons, mythical)
🧸  Objects &amp;amp; Everyday       (typewriters, books, vinyl)
💭  Emotions/Concepts       (nostalgia, tension, wonder)
🌀  Abstract/Conceptual     (fractals, mandalas, neural nets)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;How-to-use cheat sheet&lt;/strong&gt; (page 3) — 4 example combos with full breakdowns&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Compatibility matrix&lt;/strong&gt; — which commands work on Midjourney vs DALL-E 3 vs Leonardo vs SDXL vs Flux vs ChatGPT&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;10 quick workflows&lt;/strong&gt; — "turn your photo into anime," "generate a product catalog," "create a YouTube thumbnail set"&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Grab the complete handbook
&lt;/h2&gt;

&lt;p&gt;Building this library was a rabbit hole — I dug through Midjourney's v7 changelog, DALL-E 3's latest parameter updates, Leonardo.ai's 2025 feature drops, and the SDXL/Flux ecosystem to make sure every one of these 1027 commands has an accurate compatibility tag.&lt;/p&gt;

&lt;p&gt;The result is a 34-page PDF — not a wall of text, but a scannable command matrix. Print it. Bookmark it. Stick it beside your monitor. In a week, &lt;code&gt;/cyberpunk /neon /ar-9-16 /no-text&lt;/code&gt; will feel as natural as writing your name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://4693433176360.gumroad.com/l/promptvault" rel="noopener noreferrer"&gt;Get the AI Slash Commands Handbook on Gumroad&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's the one PDF you'll reach for every time you fire up an image generator — because once you start chaining commands, full-sentence prompting starts to feel archaic.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This handbook covers slash-command shorthand used by Midjourney, DALL-E 3, Leonardo.ai, Stable Diffusion, Flux, and ChatGPT image generation. Platform names and versions referenced are accurate as of August 2026.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Bonus: 5 chaining recipes for any style (dev.to edition)
&lt;/h3&gt;

&lt;p&gt;Copy-paste any of these into Midjourney, Leonardo, or ChatGPT &lt;code&gt;/imagine&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cyberpunk portrait&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/portrait /cyberpunk /neon /rain /ar-9-16 /stylize-high /quality-high
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Product hero shot&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/producthero /studio /softbox /glass-render /ar-16-9 /no-text /quality-high
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Movie poster&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/movieposter /cinematic /dramaticlight /ar-2-3 /stylize-medium /filmgrain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Educational diagram&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/scientificdiagram /infographic /3dmap /colorize /ar-16-9 /labelled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Social media thumbnail&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/youtube-thumbnail /viralthumbnail /boldad /highcontrast /ar-16-9 /no-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each chain = 1 foundation + 1 output format + 2–3 style/perspective modifiers. The full handbook gives you 1027 commands to remix however you want.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Open source Palantir tracking every plane, ship, satellite — built in a weekend</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sat, 29 Aug 2026 09:21:14 +0000</pubDate>
      <link>https://dev.to/chizee/open-source-palantir-tracking-every-plane-ship-satellite-built-in-a-weekend-5gd9</link>
      <guid>https://dev.to/chizee/open-source-palantir-tracking-every-plane-ship-satellite-built-in-a-weekend-5gd9</guid>
      <description>&lt;p&gt;Just read &lt;a class="mentioned-user" href="https://dev.to/chizee"&gt;@chizee&lt;/a&gt;'s deep dive on God's Eye View — an ex-Google Maps PM open-sourced a browser-based 3D globe tracking every aircraft, ship, satellite, and CCTV camera on Earth in real time, under MIT license. One Google Maps API key and that's it.&lt;/p&gt;

&lt;p&gt;The internet called it "vibe-coded Palantir". Palantir's co-founder noticed. Within 48 hours, the whole thing was on GitHub.&lt;/p&gt;

&lt;p&gt;What's wild: it runs in your browser, every line of code is inspectable, and it models real assets (not people). The engineering — world-stable icons, SGP4 orbital propagation, terrain-aware positioning — is genuinely impressive for a weekend project.&lt;/p&gt;

&lt;p&gt;Read the full breakdown: &lt;a href="https://dev.to/chizee/wait-we-got-open-source-palantir-before-gta-vi-1e2o"&gt;https://dev.to/chizee/wait-we-got-open-source-palantir-before-gta-vi-1e2o&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's the most surprising live-trackable asset on the globe? The ISS orbital replay? Undersea cables? Fire detections? Drop a comment below!&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Wait, We Got Open Source Palantir Before GTA VI?</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Thu, 27 Aug 2026 23:02:28 +0000</pubDate>
      <link>https://dev.to/chizee/wait-we-got-open-source-palantir-before-gta-vi-1e2o</link>
      <guid>https://dev.to/chizee/wait-we-got-open-source-palantir-before-gta-vi-1e2o</guid>
      <description>&lt;h1&gt;
  
  
  Wait, We Got Open Source Palantir Before GTA VI?
&lt;/h1&gt;

&lt;p&gt;An ex-Google Maps PM just dropped a browser-based globe that tracks every plane, ship, satellite, and CCTV camera on Earth in real time — and put the whole thing on GitHub under an MIT license. The internet called it "vibe-coded Palantir." The actual co-founder of Palantir noticed.&lt;/p&gt;

&lt;p&gt;Here is how a weekend project went from spy-thriller UI to open-source reality.&lt;/p&gt;




&lt;h2&gt;
  
  
  The demo that broke the internet
&lt;/h2&gt;

&lt;p&gt;Three minutes into Bilawal Sidhu's YouTube walkthrough, he points at a military helicopter doing racetrack patterns over Fort Rucker, Alabama. The amber icon on the 3D globe isn't just a dot — it banks into actual turns, holding the training hold that every military pilot learns in initial contact school.&lt;/p&gt;

&lt;p&gt;"Those loops are basically training patterns," he says.&lt;/p&gt;

&lt;p&gt;That's when it stops feeling like a tech demo. The globe is not showing his data or his simulation. It is showing the real sky, right now, and you can ask it questions about what is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "vibe-coded Palantir" moment
&lt;/h2&gt;

&lt;p&gt;Sidhu spent six years at Google building Immersive View — the photorealistic 3D Maps experience that lets you fly over a city before you visit. He has 2.1 million YouTube subscribers and runs a TED-curated channel on spatial computing. When the God's Eye View demo dropped, one commenter joked he had "vibe-coded Palantir."&lt;/p&gt;

&lt;p&gt;Joe Lonsdale saw it too. Within 48 hours of the video going viral, Sidhu — now CEO of a stealth startup and an a16z scout — did something no defense contractor would ever do: he open-sourced the whole thing.&lt;/p&gt;

&lt;p&gt;GitHub. MIT License. One Google Maps API key. That is it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually get
&lt;/h2&gt;

&lt;p&gt;The app runs in your browser on a photorealistic 3D globe (Google Photorealistic 3D Tiles plus CesiumJS). Thirteen live data layers, ten of them free and keyless. Here is how the demo unfolds:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 1 — Military training over Alabama.&lt;/strong&gt; Military flight traffic rendered in amber (via adsb.lol). Click any aircraft and you are in its cockpit view, with augmented reality labels on everything within a 250 km radius — other aircraft, ships at sea, mapped installations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 2 — Austin, by voice command.&lt;/strong&gt; "Take me to the Texas State Capitol." The camera glides there, orbits slowly. "Turn on the CCTV layer and annotate the grounds." Building outlines appear. "What monuments are nearby?" They are listed, marked, and connected with walking directions to the Tahhano Monument.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 3 — Real traffic, real cameras.&lt;/strong&gt; Over Austin, turn on the TomTom traffic layer. Congestion colors the streets. Click a jammed intersection and the app jumps to the nearest public camera — projected into the 3D city, not stuck on as a 2D embed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 5 — Infrastructure everywhere.&lt;/strong&gt; Undersea cables near the Bahamas — 712 mapped routes you can dive beneath. Dams appear on demand in China (704 of them). Data centers (4,351), plotted globally. NASA fire detections flash red dots you can inspect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 7 — Orbit.&lt;/strong&gt; Turn on the satellite layer and click the ISS. You ride along at orbital distance, orbit ring visible, watching it cross over Ukraine while ground tracks update via SGP4 propagation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 9 — Falcon 9 replay.&lt;/strong&gt; Pick a recent launch, hit play, watch the ascent — scrubbable from 0.25x to 4x. Labeled RECONSTRUCTED ESTIMATE, since it is one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 11 — The voice whiteboard.&lt;/strong&gt; "Draw the walking route from the Capitol to Zilker Park." A street-following path traces itself through the 3D city. "Fly it." The camera banks into turns like a drone shot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minute 13 — Radio.&lt;/strong&gt; "Play a news radio station near Austin." An analog tuner appears. Drag the needle — the globe flies to each of the 750 worldwide broadcasters, one real place at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it is built
&lt;/h2&gt;

&lt;p&gt;The stack is stripped down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vanilla JavaScript — no React, no Vue, no framework overhead&lt;/li&gt;
&lt;li&gt;CesiumJS — the 3D globe engine&lt;/li&gt;
&lt;li&gt;Vite — build tool&lt;/li&gt;
&lt;li&gt;Google Photorealistic 3D Tiles — the planet (the one paid key)&lt;/li&gt;
&lt;li&gt;OpenAI Realtime API — voice only (optional, $5 session cap)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No framework is the real statement. Sidhu could have shipped this as a Next.js app with a dozen dependencies. Instead, the entire app boots in 1.86 seconds on a laptop and the codebase is small enough to actually read.&lt;/p&gt;

&lt;p&gt;The engineering that makes it feel real:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;World-stable icons.&lt;/strong&gt; Aircraft and ships point along their true real-world heading at every camera angle — not just on the current screen. Per-frame screen-space course projection. Most tracking apps break this when you tilt or pan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smooth motion from choppy data.&lt;/strong&gt; Feeds arrive every 15 to 30 seconds. The globe renders one interval behind real time and interpolates between fixes using dead reckoning. No teleporting icons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Honest satellites.&lt;/strong&gt; SGP4 orbital propagation with GMST realignment keeps orbit rings locked to their satellites. The ISS does not slide across the sky like it is on greased glass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terrain-aware positioning.&lt;/strong&gt; Entity heights run through a real vertical datum (geoid-aware, sampled against the rendered terrain mesh). Aircraft park on runways. Cameras stand on street corners. Nothing floats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quota-governed proxies.&lt;/strong&gt; The paid feeds (OpenSky, TomTom) run behind cached, budget-governed proxies. An afternoon of exploring will not torch your API allowance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one thing you pay for
&lt;/h2&gt;

&lt;p&gt;Google Maps. That is the only paid key you need. Google gives 1,000 free 3D-tile sessions per month — each good for up to three hours of rendering. A solo user rarely leaves the free tier. After that, about $6 per 1,000 sessions.&lt;/p&gt;

&lt;p&gt;OpenAI voice is also metered, but the app enforces a hard $5 session cap and warns at $2.&lt;/p&gt;

&lt;p&gt;Everything else — flights, ships, satellites, earthquakes, CCTV, radio, bikeshare, fire detections, space launches — is free. No account, no signup. Just open the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Palantir comparison, unpacked
&lt;/h2&gt;

&lt;p&gt;The joke landed because Palantir's whole thing is taking public data and making it look like a classified ops room. God's Eye View achieves the same aesthetic — FLIR overlays, tactical HUD, cockpit views — but the interface runs in your browser, under your control, and every line of code is inspectable.&lt;/p&gt;

&lt;p&gt;Palantir builds enterprise software for government agencies. God's Eye View is a browser app any teenager with a laptop can clone, fork, and extend. That is why the comparison is almost too perfect. Sidhu took the look and feel of billion-dollar geospatial intelligence and made the entry fee zero, the distribution model GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real cost of going back in time
&lt;/h2&gt;

&lt;p&gt;Sidhu's closing admission:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Build in this space for a week and you learn that the present is the cheap part. The moment you try to go back in time — tiling, serving, and scrubbing what happened and what changed at any real resolution — the data gets expensive and the compute gets brutal."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The free layer does real-time only. Yesterday's traffic, last week's flight paths, historical fire perimeters? That is where enterprise contracts kick in. Sidhu's team at halfpixel.ai is building that part for paying customers. It will not be open source or free.&lt;/p&gt;

&lt;p&gt;But the baseline — today, right now — is the real thing. Track anything moving on the planet. Ask questions in natural language. Annotate the world around you. Replay a rocket launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  No people tracking — and that matters
&lt;/h2&gt;

&lt;p&gt;Sidhu drew a line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This project models events, assets, infrastructure, and systems — aircraft, vessels, satellites, fires, cameras, cities. It does not build features for named-person search, face recognition, or tracking individuals, and pull requests that cross that line won't be merged."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a landscape where every "open source OSINT" project pivots into surveillance-for-hire, that ethical boundary is as notable as the engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go break it
&lt;/h2&gt;

&lt;p&gt;GitHub: github.com/bilawalsidhu/gods-eye-view&lt;/p&gt;

&lt;p&gt;It runs on public data, clear sources, and local-first execution. No secrets, no private datasets, no mystery scraping. Secret-bearing API keys (OpenAI, AISStream, OpenSky OAuth, TomTom, FIRMS) stay server-side — the browser only gets a short-lived session token.&lt;/p&gt;

&lt;p&gt;Or, if you are not a developer: install Claude Code, Codex, or Cursor, and paste:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Clone github.com/bilawalsidhu/gods-eye-view and set it up. Walk me through the Google Maps key, set a billing alert and usage quota, and start the dev server. I am not a developer — explain as you go."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That one key is the whole entry fee. Everything else lights up from there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is yours. Have fun with it. Break it. Extend it. Do amazing things with it. I cannot wait to see what you cook up."&lt;br&gt;
— Bilawal Sidhu&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Originally published on omenabyte.com: &lt;a href="https://omenabyte.com/blog/open-source-palantir-gods-eye-view" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/open-source-palantir-gods-eye-view&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>geospatial</category>
      <category>osint</category>
      <category>webgl</category>
    </item>
    <item>
      <title>Postgres Can Do Typo-Tolerant Search. You Don't Need Elasticsearch Yet.</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 23 Aug 2026 17:01:46 +0000</pubDate>
      <link>https://dev.to/chizee/postgres-can-do-typo-tolerant-search-you-dont-need-elasticsearch-yet-2k6</link>
      <guid>https://dev.to/chizee/postgres-can-do-typo-tolerant-search-you-dont-need-elasticsearch-yet-2k6</guid>
      <description>&lt;h1&gt;
  
  
  Launch Workspace — "Just Use Postgres" Week 2
&lt;/h1&gt;

&lt;p&gt;Route: &lt;strong&gt;A (canonical build) — DRAFTED ✅ (cron will build + ship Aug 16)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Dev.to title:&lt;/strong&gt; Postgres Can Do Typo-Tolerant Search. You Don't Need Elasticsearch Yet.&lt;br&gt;
&lt;strong&gt;Slug:&lt;/strong&gt; &lt;code&gt;replace-elasticsearch-with-postgres-search&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Canonical URL:&lt;/strong&gt; &lt;a href="https://omenabyte.com/blog/replace-elasticsearch-with-postgres-search" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-elasticsearch-with-postgres-search&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;dev.to tags:&lt;/strong&gt; postgres, database, search, tutorial&lt;br&gt;
&lt;strong&gt;Cover:&lt;/strong&gt; &lt;a href="https://omenabyte.com/blog/just-use-postgres-cover.png" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/just-use-postgres-cover.png&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Series:&lt;/strong&gt; The Field Manual Series&lt;br&gt;
&lt;strong&gt;Medium topics (for the manual import step):&lt;/strong&gt; &lt;code&gt;PostgreSQL, Databases, SQL, Web Development, Software Engineering&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;A search bar feels like an Elasticsearch problem the moment someone asks for "did you mean...?" or relevance ranking. So the data gets duplicated into a second cluster, a sync job gets built to keep it current, and now there are two sources of truth for the same rows.&lt;/p&gt;

&lt;p&gt;Postgres already has both stemmed search and typo tolerance built in — one native, one a very old, very stable extension.&lt;/p&gt;
&lt;h2&gt;
  
  
  Stemmed, ranked search with tsvector
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;tsvector&lt;/code&gt; strips stop words and reduces text to root forms — "running" becomes "run" — so a search for one form matches the others, ranked by relevance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;search_vector&lt;/span&gt; &lt;span class="n"&gt;tsvector&lt;/span&gt;
  &lt;span class="k"&gt;GENERATED&lt;/span&gt; &lt;span class="n"&gt;ALWAYS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to_tsvector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coalesce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;coalesce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;STORED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_articles_search&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;search_vector&lt;/span&gt; &lt;span class="o"&gt;@@&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'postgres &amp;amp; scaling'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;ts_rank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_tsquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'english'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'postgres &amp;amp; scaling'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;coalesce()&lt;/code&gt; isn't decoration — I found this the hard way. In Postgres, &lt;code&gt;text || NULL&lt;/code&gt; evaluates to &lt;code&gt;NULL&lt;/code&gt;. Skip the coalesce, and the very first article with an empty body silently drops out of search entirely, with no error to tell you why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typo tolerance with pg_trgm
&lt;/h2&gt;

&lt;p&gt;For the "did you mean" experience, &lt;code&gt;pg_trgm&lt;/code&gt; breaks text into overlapping three-letter chunks and matches on similarity instead of exact spelling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;EXTENSION&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;pg_trgm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_articles_title_trgm&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;GIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="n"&gt;gin_trgm_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="s1"&gt;'Postgress'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;  &lt;span class="c1"&gt;-- misspelled, still matches&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;word_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Postgress'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice this uses &lt;code&gt;&amp;lt;%&lt;/code&gt; (&lt;code&gt;word_similarity&lt;/code&gt;), not the more commonly-shown &lt;code&gt;%&lt;/code&gt; (&lt;code&gt;similarity&lt;/code&gt;). That distinction actually matters: &lt;code&gt;%&lt;/code&gt; compares two &lt;em&gt;entire strings&lt;/em&gt; against each other. Test it yourself — a completely ordinary title like "Scaling Postgres in Production" scores &lt;em&gt;below&lt;/em&gt; the default match threshold against "Postgress," because the operator is comparing the misspelled word to the whole sentence, not to the word within it. &lt;code&gt;word_similarity&lt;/code&gt; checks the query against individual words inside the longer string instead, which is what "typo-tolerant search" actually means in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats standing up a search cluster
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The index lives transactionally with the row — no reindex pipeline to keep in sync.&lt;/li&gt;
&lt;li&gt;Ranking is built in via &lt;code&gt;ts_rank&lt;/code&gt;, not bolted on.&lt;/li&gt;
&lt;li&gt;One fewer cluster to provision, patch, and pay for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Elasticsearch still wins
&lt;/h2&gt;

&lt;p&gt;Distributed log analytics at serious scale, or if you're already deep in its observability ecosystem (Kibana dashboards, log aggregation) rather than a single application search bar. For "let users search my app's content," Postgres covers the overwhelming majority of real cases.&lt;/p&gt;




&lt;p&gt;This is one of eight infrastructure swaps in &lt;strong&gt;Just Use Postgres&lt;/strong&gt;, a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance before it went in the book.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Get the field manual&lt;/strong&gt; — launch price &lt;strong&gt;$14&lt;/strong&gt; instead of walking into a $50/month managed-search invoice: &lt;a href="https://payhip.com/omenabyte" rel="noopener noreferrer"&gt;https://payhip.com/omenabyte&lt;/a&gt;&lt;br&gt;
🐳 Or take the &lt;strong&gt;$24 bundle&lt;/strong&gt; with the full &lt;code&gt;docker-compose up&lt;/code&gt; starter repo — all 8 modules as tested, runnable migrations + seed data: &lt;a href="https://4693433176360.gumroad.com/" rel="noopener noreferrer"&gt;https://4693433176360.gumroad.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Read this on omenabyte.com → &lt;a href="https://omenabyte.com/blog/replace-elasticsearch-with-postgres-search" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-elasticsearch-with-postgres-search&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>search</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Replaced Redis and RabbitMQ With 15 Lines of Postgres</title>
      <dc:creator>Chizee</dc:creator>
      <pubDate>Sun, 09 Aug 2026 13:01:00 +0000</pubDate>
      <link>https://dev.to/chizee/i-replaced-redis-and-rabbitmq-with-15-lines-of-postgres-3266</link>
      <guid>https://dev.to/chizee/i-replaced-redis-and-rabbitmq-with-15-lines-of-postgres-3266</guid>
      <description>&lt;h1&gt;
  
  
  Launch Workspace — "Just Use Postgres" Week 1
&lt;/h1&gt;

&lt;p&gt;Route: &lt;strong&gt;TBD&lt;/strong&gt; (A = canonical build on omenabyte.com → dev.to API · B = dev.to-first · C = draft-only manual publish)&lt;br&gt;
Decision made: &lt;em&gt;pending Boss's pick&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  ARTICLE 1 — dev.to-optimized draft
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Title:&lt;/strong&gt; I Replaced Redis and RabbitMQ With 15 Lines of Postgres&lt;br&gt;
&lt;strong&gt;Tags:&lt;/strong&gt; postgres, database, backend, tutorial&lt;br&gt;
&lt;strong&gt;Cover image:&lt;/strong&gt; &lt;code&gt;Just-Use-Postgres-Field-Manual-cover.png&lt;/code&gt; (blueprint elephant, navy/amber — matches dev.to dark theme)&lt;br&gt;
&lt;strong&gt;Canonical URL (route A):&lt;/strong&gt; &lt;code&gt;https://omenabyte.com/blog/replace-redis-rabbitmq-with-postgres&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;Every background job system I've built started the same way: &lt;em&gt;"we'll just add Redis for the queue."&lt;/em&gt; Then six months later there's a broker to patch, secure, monitor, and pay for — doing a job Postgres can do with one SQL clause.&lt;/p&gt;

&lt;p&gt;That clause is &lt;code&gt;FOR UPDATE SKIP LOCKED&lt;/code&gt;, and once you've used it, a message broker feels like overkill for most job-queue workloads.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem with a naive SQL queue
&lt;/h2&gt;

&lt;p&gt;The reason people avoid building a queue directly on a table is real: two workers can grab the same "pending" row at the same time, one locks it, and the other sits there waiting. That's a legitimate deadlock risk — if you build it naively.&lt;/p&gt;
&lt;h2&gt;
  
  
  The fix: SKIP LOCKED
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;SKIP LOCKED&lt;/code&gt; tells Postgres: if a row is already locked by another transaction, don't wait for it — skip straight to the next one. That single behavior turns an ordinary table into a safe, concurrent queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="n"&gt;bigserial&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt;     &lt;span class="n"&gt;jsonb&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt;      &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;locked_at&lt;/span&gt;   &lt;span class="n"&gt;timestamptz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt;  &lt;span class="n"&gt;timestamptz&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Without this, the query below does a full table scan on every poll&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_jobs_status_created&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pending'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'processing'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the actual dequeue query every worker runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;next_job&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt;
     &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'processing'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;locked_at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="s1"&gt;'5 minutes'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;
  &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;SKIP&lt;/span&gt; &lt;span class="n"&gt;LOCKED&lt;/span&gt;
  &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'processing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;locked_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;next_job&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="n"&gt;RETURNING&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;locked_at&lt;/code&gt; check matters more than it looks. It's the equivalent of a message queue's &lt;em&gt;visibility timeout&lt;/em&gt; — if a worker crashes mid-job, the job doesn't stay stuck in &lt;code&gt;processing&lt;/code&gt; forever. Another worker reclaims it after five minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  I actually tested this for duplicates
&lt;/h2&gt;

&lt;p&gt;I ran this exact query five times in a row against a seeded table: three fresh jobs and one simulated crashed job. Every job came back exactly once, in order, and the crashed job was correctly reclaimed on the fourth call. Zero duplicates, zero races.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats adding Redis for most teams
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No broker to operate.&lt;/strong&gt; Nothing new to patch, secure, or monitor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job history lives with your data.&lt;/strong&gt; You can join a job row straight to the order or user it belongs to — try doing that across two databases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crashes don't lose work.&lt;/strong&gt; The reclaim logic above handles it natively.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Redis still wins
&lt;/h2&gt;

&lt;p&gt;If you need sub-millisecond pub/sub fan-out to thousands of concurrent WebSocket clients, or a pure in-memory cache absorbing extreme read traffic, that's a different problem — Redis is still the right tool there. But &lt;em&gt;"give my background jobs somewhere safe to live"&lt;/em&gt; almost never needs a separate service.&lt;/p&gt;




&lt;p&gt;This is one of eight infrastructure swaps in &lt;strong&gt;Just Use Postgres&lt;/strong&gt;, a 24-page field manual on replacing MongoDB, Redis, Elasticsearch, Pinecone, and more with the database you're probably already running. Every recipe in it — including this one — was run against a live Postgres instance before it went in the book.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Get the field manual&lt;/strong&gt; — launch price &lt;strong&gt;$14&lt;/strong&gt; instead of walking into a $50/month managed-Redis invoice: &lt;a href="https://payhip.com/omenabyte" rel="noopener noreferrer"&gt;https://payhip.com/omenabyte&lt;/a&gt;&lt;br&gt;
🐳 Or take the &lt;strong&gt;$24 bundle&lt;/strong&gt; with the full &lt;code&gt;docker-compose up&lt;/code&gt; starter repo — all 8 modules as tested, runnable migrations + seed data: &lt;a href="https://4693433176360.gumroad.com/" rel="noopener noreferrer"&gt;https://4693433176360.gumroad.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Read this on omenabyte.com → &lt;a href="https://omenabyte.com/blog/replace-redis-rabbitmq-with-postgres" rel="noopener noreferrer"&gt;https://omenabyte.com/blog/replace-redis-rabbitmq-with-postgres&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>backend</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
