<?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: Ben Halpern</title>
    <description>The latest articles on DEV Community by Ben Halpern (@ben).</description>
    <link>https://dev.to/ben</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%2F1%2Fbabb96d0-9cd2-49bc-a412-2dc4caf94c2a.png</url>
      <title>DEV Community: Ben Halpern</title>
      <link>https://dev.to/ben</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ben"/>
    <language>en</language>
    <item>
      <title>Letting the DEV Community Weigh in on the Topics of AIE</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Thu, 02 Jul 2026 15:24:12 +0000</pubDate>
      <link>https://dev.to/dailycontext/letting-the-dev-community-weigh-in-on-the-topics-of-aie-439l</link>
      <guid>https://dev.to/dailycontext/letting-the-dev-community-weigh-in-on-the-topics-of-aie-439l</guid>
      <description>&lt;p&gt;I’m at the AI Engineer World’s Fair in San Francisco, where the vibes are enthusiastic. However, enthusiasm does not mean hype. The content has largely been grounded in pragmatic problem-solving. My sense is that the industry is finally homing in on the "jobs to be done" conversation over model hype — though I could still do without the “maxxing” suffix applied to everything.&lt;/p&gt;

&lt;p&gt;To mirror the tone of the conference itself — where raw hype isn't quite as cool as it used to be — the global DEV Community has been providing excellent commentary on the reporting we’ve been publishing. &lt;a href="https://dev.to/aie"&gt;&lt;em&gt;The Daily Context&lt;/em&gt;&lt;/a&gt; newspaper has been distributed every day at the conference to help attendees stay caught up on broader themes, but it’s also gone out on DEV for thousands of remote developers to read and weigh in on.&lt;/p&gt;

&lt;p&gt;To close the feedback loop and elevate the conversation, here are a few standout quotes and themes from the community that caught my eye.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infinite Code and Shifting Constraints
&lt;/h2&gt;

&lt;p&gt;We talk a lot about AI enabling us to ship infinite code, but our community quickly pointed out that raw volume is a vanity metric. &lt;a href="https://dev.to/raju_dandigam/comment/3ad4o"&gt;Raju Dandigam&lt;/a&gt; cut straight to the core of the issue, noting that:&lt;/p&gt;

&lt;p&gt;"Choke points govern value, not code volume. The teams who win won't be the ones generating the most, they'll be the ones who made the choke points cheap to clear."&lt;/p&gt;

&lt;p&gt;When code generation becomes free, our bottlenecks move downstream to architectural cohesion, verification, and code review. As &lt;a href="https://dev.to/nazar_boyko/comment/3abhl"&gt;Nazar Boyko&lt;/a&gt; added, a development command center only helps if it surfaces the current constraint; otherwise, you've just built a faster way to watch the wrong thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blame Shifting and the Frontier Default
&lt;/h2&gt;

&lt;p&gt;Another fascinating debate unfolded around why developers stubbornly default to expensive frontier models for trivial tasks. While it's easy to preach about "tokenomics," &lt;a href="https://dev.to/kingaiwork/comment/3abao"&gt;kingai&lt;/a&gt; offered a brutally honest psychological perspective. The frontier default isn’t always a capability hedge — it’s a blame-shifting hedge. If a fast model fails, it's your fault; if a massive frontier model fails, you get to blame the model.&lt;/p&gt;

&lt;p&gt;To break this habit, &lt;a href="https://dev.to/vollos/comment/3aa40"&gt;Pon&lt;/a&gt; argued against making users choose between models upfront via complex dropdowns. Instead, software should default to fast, cheap models out of the gate, gating escalation on a deterministic check of the output structure rather than the model's own self-reported confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Architecture: Claims vs. Evidence
&lt;/h2&gt;

&lt;p&gt;The structural shift toward treating an AI agent as an append-only event log generated some of our sharpest technical pushback. While the log-as-state model ensures exceptional reliability, &lt;a href="https://dev.to/alice_31281c3fed5d0305db5/comment/3abcl"&gt;Alice&lt;/a&gt; dropped a brilliant warning: The log faithfully resumes claims, not objective truth. If an agent records a confident status event saying a file is empty without an underlying tool confirmation, the log simply hardcodes a durable hallucination.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mateo_ruiz_6992b1fce47843/comment/3aakg"&gt;Mateo Ruiz&lt;/a&gt; proposed an elegant architectural split modeled after double-entry bookkeeping: Maintain a claim ledger for state resumption, but use an independent evidence ledger (file diffs, exit codes) to handle real-world verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Tax of Autonomous Decisions
&lt;/h2&gt;

&lt;p&gt;Finally, we have to look closely at dependency selection. When you ask an agent to build a feature, it implicitly chooses your library stack for you. &lt;a href="https://dev.to/francistrdev/comment/3ack9"&gt;FrancisTRᴅᴇᴠ&lt;/a&gt; highlighted the profound security edge here, warning that a model's authoritative delivery easily disarms human checkers, leaving the door wide open for typosquatted packages or supply-chain attacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practicality Wins the Cycle
&lt;/h2&gt;

&lt;p&gt;The DEV community isn't getting swept up in the sci-fi dream of fully unsupervised autopilot. The developers winning this cycle are applying basic, defensive engineering principles — making inputs predictable, creating strict code harnesses, and testing outputs rigorously.&lt;/p&gt;

&lt;p&gt;Frankly, I think that mirrors the tone of the conference, and this is the feedback loop our industry is in right now. Everyone sees a form of progress, but nobody wants their AI-pilled manager to come back from the market having been sold magic beans.&lt;/p&gt;

</description>
      <category>aie</category>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Fragile Balance of AI Development: Individual Flow vs. Collective Context</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Thu, 02 Jul 2026 15:00:21 +0000</pubDate>
      <link>https://dev.to/dailycontext/the-fragile-balance-of-ai-development-individual-flow-vs-collective-context-2f49</link>
      <guid>https://dev.to/dailycontext/the-fragile-balance-of-ai-development-individual-flow-vs-collective-context-2f49</guid>
      <description>&lt;p&gt;As much AI-driven development has normalized, we are still in the Wild West. While we are closer to homing in on what “best practices” actually mean, defining them remains a moving target. Right now, a fascinating tension is emerging between the workflows we build for ourselves and the systems we build for our teams.&lt;/p&gt;

&lt;p&gt;At the &lt;strong&gt;individual level&lt;/strong&gt;, best practices are a bit of a “choose your own adventure” setup, and that’s perfectly fine — with one major caveat. It’s incredibly easy to drift into isolated silos when you’re running your own little fleet of developer agents.&lt;/p&gt;

&lt;p&gt;True individual mastery isn’t just about prompt engineering; it’s about &lt;strong&gt;context management&lt;/strong&gt; and &lt;strong&gt;disorganization control&lt;/strong&gt;. It’s setting up the right Model Context Protocol (MCP) servers to bridge your tools and services, and mastering the feedback loops necessary to manage parallel work. When you’re orchestrating multiple agent workflows, the core skill is balancing your own cognitive capacity — observing and inferring state across different tasks to ensure the train doesn’t run off the tracks.&lt;/p&gt;

&lt;p&gt;But things get exponentially harder at the &lt;strong&gt;team level&lt;/strong&gt;. Collective best practices require finding common ground, which inherently sits just behind the bleeding edge. If a team constantly swaps core architecture for the newest shiny object, velocity stalls. Instead, we need a predictable, accelerated pace for tool adoption that fits into the team’s collective brain without causing whiplash.&lt;/p&gt;

&lt;p&gt;This requires a specific archetype of technical leader: someone deeply anchored in “traditional” production engineering, security, and DevOps, but possessing the pragmatism to integrate AI acceleration safely. While individual devs need a security-conscious mindset to protect their environments, the team level is where that mindset becomes mission-critical. It’s the ultimate gatekeeper for what code actually reaches production.&lt;/p&gt;

&lt;p&gt;To prevent total divergence, teams must actively invest in intentional knowledge sharing and inspiration sessions. If we don’t intentionally bridge the gap between individual flow and collective guardrails, we risk fracturing our engineering culture.&lt;/p&gt;

</description>
      <category>aie</category>
      <category>agents</category>
      <category>mcp</category>
      <category>devops</category>
    </item>
    <item>
      <title>From Harness Engineering to Evals: What’s Trending at AI Engineer</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Wed, 01 Jul 2026 14:34:35 +0000</pubDate>
      <link>https://dev.to/dailycontext/from-harness-engineering-to-evals-4212</link>
      <guid>https://dev.to/dailycontext/from-harness-engineering-to-evals-4212</guid>
      <description>&lt;p&gt;I’m at the &lt;a href="http://ai.engineer/worldsfair/2026" rel="noopener noreferrer"&gt;AI Engineer conference in San Francisco&lt;/a&gt; this week. The event has every major brand-name sponsor you’d expect, a lineup of internet-famous project maintainers on stage, and a massive schedule covering which more or less &lt;a href="https://dev.to/dailycontext/ai-engineer-meets-ai-engineer-1klj"&gt;has something for everyone&lt;/a&gt;. It’s easy to get lost in the noise. I spent my time trying to figure out what themes are actually real.&lt;/p&gt;

&lt;p&gt;With dozens of tracks and thousands of builders, the ecosystem looks incredibly fractured. But if you look at what engineers are actually putting into production, the chaos collapses into a clear pattern. The industry is moving past simple chat interfaces and treating large language models like central processing units inside a larger, highly structured software architecture—essentially an LLM Operating System.&lt;/p&gt;

&lt;p&gt;I cataloged everything I was seeing, dug into the technical tracks, and came away with these six themes. &lt;strong&gt;This is not my endorsement&lt;/strong&gt;, and I have not separated the hype from the real. Take these brief summaries as jumping-off points to help you go deeper if any of these ideas trigger your curiosity.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Shift to Repository-Scale “Software Factories”
&lt;/h2&gt;

&lt;p&gt;For the last few years, AI in development was basically tab-complete. You wrote a line of code, an assistant suggested the next few tokens, and you moved on.&lt;/p&gt;

&lt;p&gt;That single-file approach is quickly becoming obsolete. The focus has shifted to repository-scale, multi-agent systems—what people are calling &lt;strong&gt;Software Factories&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of writing lines of code alongside an AI assistant, developers are managing fleets of agents that operate across entire codebases. For example, Uber shared details on uReview, their internal code review engine. It uses agents to autonomously review pull requests, spin up localized test suites, catch edge cases, and commit fixes back to the branch before a human even looks at it.&lt;/p&gt;

&lt;p&gt;To make this reliable, engineers are plugging compilers and linters directly into the agent’s feedback loop. If the generated code fails to compile, the raw error output is fed right back into the system prompt. The model reads its own error, fixes the bug, and re-runs the check autonomously.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Hardening Systems with “Harness Engineering”
&lt;/h2&gt;

&lt;p&gt;There’s a common realization on the conference floor right now: &lt;em&gt;“Everyone is building an agent harness, but nobody calls it that.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;LLMs are inherently probabilistic and non-deterministic. Software infrastructure, however, requires predictable inputs and outputs. To fix this, teams are formalizing a core systems discipline: &lt;strong&gt;Harness Engineering.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The “harness” is the strict software wrapper built around a model to enforce constraints, manage state, and prevent infinite execution loops.&lt;/p&gt;

&lt;center&gt;
+--------------------------------------------------------+&lt;br&gt;
|                   THE AGENT HARNESS                    |&lt;br&gt;
+--------------------------------------------------------+&lt;br&gt;
| 1. Durable Execution (State preservation &amp;amp; retries)    |&lt;br&gt;
+--------------------------------------------------------+&lt;br&gt;
| 2. Structured Outputs (Schema enforcement / Pydantic)  |&lt;br&gt;
+--------------------------------------------------------+&lt;br&gt;
| 3. Dynamic Guardrails (Input/Output sanitization)      |&lt;br&gt;
+--------------------------------------------------------+&lt;br&gt;
&lt;/center&gt; 

&lt;p&gt;&amp;nbsp;&lt;br&gt;
Instead of letting an agent run unmonitored, developers are using toolchains like Temporal or Inngest to implement &lt;strong&gt;durable execution&lt;/strong&gt;. If an agent is running a complex, multi-hour workflow and hits a network timeout, the harness preserves its memory and state. The process can resume exactly where it failed without repeating expensive API calls. Paired with libraries like Pydantic or Instructor to force strict JSON schema compliance, the harness makes unpredictable models behave like stable infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Computer Use vs. Custom APIs
&lt;/h2&gt;

&lt;p&gt;For decades, integration meant writing custom API connectors or scraping endpoints. A major theme this year is &lt;strong&gt;Computer Use&lt;/strong&gt;—building agents that navigate software exactly like a human operator does: by looking at a screen, moving a mouse, and typing commands.&lt;/p&gt;

&lt;p&gt;Enabled by better vision-language models (VLMs), these systems don’t need structured backend APIs. They take continuous screenshots of a graphical user interface (GUI), parse the visual layout to locate fields and buttons, and execute precise pixel coordinates.&lt;/p&gt;

&lt;p&gt;This has forced a shift in local developer setups. Engineers are building isolated, sandboxed terminals and open-source desktop companions (like OpenClaw) that give background agents their own virtual environments. This lets agents spin up local servers and debug files in isolation without taking over the engineer’s active screen and keyboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Context Engineering &amp;amp; “Tokenmaxxing”
&lt;/h2&gt;

&lt;p&gt;Context windows have scaled to millions of tokens, but dumping an entire codebase into a prompt is an expensive, high-latency anti-pattern.&lt;/p&gt;

&lt;p&gt;Time-to-first-token and API costs are the real bottlenecks today. Because of this, developers are focusing heavily on &lt;strong&gt;Context Engineering&lt;/strong&gt;—treating the context window as a highly optimized, dynamic memory cache rather than a static text dump.&lt;/p&gt;

&lt;p&gt;The optimization strategy generally follows a three-layer approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prefix Caching&lt;/strong&gt;: Inference engines like vLLM cache the Key-Value (KV) states of static system instructions or documentation headers. Subsequent requests reuse this cache, significantly cutting down latency and cost.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Compression&lt;/strong&gt;: Middleware layers are introduced to run semantic compression algorithms, pruning irrelevant tokens and summarizing messy chat logs before sending data to the provider.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Graph RAG &amp;amp; Hybrid Retrieval&lt;/strong&gt;: Instead of pulling raw text blocks indiscriminately, systems use structured knowledge graphs to pass only high-signal data into the active context window.&lt;br&gt;
Finish reading at link.dev.to/aie39.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Moving Past “Vibe-Based” Evaluations
&lt;/h2&gt;

&lt;p&gt;If there is one clear operational shift, it’s that vibe-based engineering is dead. Reviewing a few outputs, deciding they look reasonable, and shipping them to production is no longer an acceptable practice.&lt;/p&gt;

&lt;p&gt;The core focus of the &lt;strong&gt;Evals&lt;/strong&gt; community is on automated, multi-step simulation benchmarks. Evaluating an agent now requires spinning up an isolated virtual environment—a temporary sandbox with mock databases and network access—and letting the agent attempt a complex task. The evaluation framework doesn't grade the style of the response; it checks if the task was completed successfully, notes how many steps it took, and verifies that no security protocols were broken.&lt;/p&gt;

&lt;p&gt;Engineers are also moving away from the “Persona Trap”—giving a model a prompt like “You are a senior staff engineer.” Studies shared at the event show this approach evaluates a stylistic vibe rather than a rigorous technical capability, often introducing silent biases that degrade performance. The standard now is rigid, task-oriented testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Secure Micro-Sandboxes for Runtime Safety
&lt;/h2&gt;

&lt;p&gt;Giving an agent the authority to write code, modify files, and run terminal commands introduces severe security risks.&lt;/p&gt;

&lt;p&gt;Platform engineers are tackling this by focusing on the underlying execution layer. The industry standard has normalized around &lt;strong&gt;Micro-Sandboxes&lt;/strong&gt;. Agent-generated code is executed inside lightweight, ephemeral micro-VMs (like those from E2B or Docker) that spin up in milliseconds, handle the specific computation, and are immediately destroyed to prevent container escape or persistent file system tampering.&lt;/p&gt;

&lt;p&gt;There is also a major push toward credential masking. When agents need access to enterprise databases or third-party tools, engineers are using new delegation layers like the AAuth protocol. This grants the agent mission-bounded authority to call a tool, but prevents the agent from ever seeing or interacting with the raw API keys, neutralizing prompt injection leaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;It’s easy to skim these topics, feel a wave of FOMO, and think you’re already lagging behind if you aren’t running a fleet of micro-sandboxes or an autonomous software factory. &lt;/p&gt;

&lt;p&gt;Don’t buy into the hype. You don’t need to overhaul your entire stack by next Monday.&lt;/p&gt;

&lt;p&gt;The real takeaway from all the noise at Moscone is actually pretty reassuring: AI is just becoming regular software infrastructure. The developers who build useful things over the next few years won't be the ones chasing every flashing new model drop or complex multi-agent framework. They’ll be the ones applying basic, boring engineering principles—making their inputs predictable, testing their code rigorously, and keeping their environments secure.&lt;/p&gt;

&lt;p&gt;If you're looking for a place to start, don’t overcomplicate it. Pick a single, repetitive workflow in your day-to-day. Wrap a clean, defensive code harness around it, build a straightforward evaluation script to check its work, and see what happens. Inspiration is great, but pragmatism is what actually ships.&lt;/p&gt;

</description>
      <category>aie</category>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
    </item>
    <item>
      <title>Bottleneck Resolution is, In Fact, All the Rage in AI Engineering</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Wed, 01 Jul 2026 13:51:51 +0000</pubDate>
      <link>https://dev.to/dailycontext/bottleneck-resolution-is-in-fact-all-the-rage-in-ai-engineering-21cj</link>
      <guid>https://dev.to/dailycontext/bottleneck-resolution-is-in-fact-all-the-rage-in-ai-engineering-21cj</guid>
      <description>&lt;p&gt;The AI Engineer World's Fair here in San Francisco is fundamentally a conference for practitioners — devs who need to be productive today. While it naturally attracts folks operating on the absolute cutting edge, at the end of the day, most of us are just developers trying to ship. I touched on this in &lt;a href="https://dev.to/dailycontext/ai-engineer-meets-ai-engineer-1klj"&gt;my observations yesterday&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before arriving, I wrote abstractly about &lt;a href="https://dev.to/dailycontext/pragmatism-in-an-age-of-infinite-code-and-unavoidable-bottlenecks-1bkd"&gt;navigating unavoidable bottlenecks&lt;/a&gt; in an era of infinite code. This week, I'm seeing that theory play out in real time across the keynotes. This morning, OpenClaw creator Peter Steinberger took the stage to talk about bottlenecks in a deeply pragmatic way. The AI space is inherently glitzy, but the dialogue is finally grounding itself in the messy, practical in-between parts where things actually get done.&lt;/p&gt;

&lt;p&gt;Bottleneck resolution is boring, but it's good boring. I don't need keynotes that promise a future where friction magically vanishes; I want the patterns and engineering discipline required to solve the constraints we have right now. It's the exact same thing we've always wanted from traditional software eras — and it's exactly where we've arrived with AI.&lt;/p&gt;

</description>
      <category>aie</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>AI Engineer Meets AI Engineer</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Tue, 30 Jun 2026 15:21:36 +0000</pubDate>
      <link>https://dev.to/dailycontext/ai-engineer-meets-ai-engineer-1klj</link>
      <guid>https://dev.to/dailycontext/ai-engineer-meets-ai-engineer-1klj</guid>
      <description>&lt;p&gt;I'm sitting through day one of &lt;a href="https://www.ai.engineer/worldsfair/2026" rel="noopener noreferrer"&gt;AI Engineer World's Fair San Francisco&lt;/a&gt;, and I'm struck by how effectively the schedule embraces the beautiful fuzziness of "AI." In the past, I might have questioned a conference that lumps together developers who "just use the tools" with those diving into the core science. But being here, it clicks: both are AI engineers, even if their day-to-day jobs look entirely different.&lt;/p&gt;

&lt;p&gt;Look at the workshop lineup. On one end, you have sessions like Kent C. Dodds' Product Engineering for Software Developers, targeting practitioners building practical, agentic workflows. On the opposite end of the spectrum, you have Daniel Han from Unsloth leading a deep dive into Special topics in Kernels, RL, and Reward Hacking.&lt;/p&gt;

&lt;p&gt;One is about high-level orchestration, UX, and shipping product; the other is about the raw, nuts-and-bolts infrastructure of inference and model optimization.&lt;/p&gt;

&lt;p&gt;Does it make sense to commingle these two distinct roles under one banner?&lt;/p&gt;

&lt;p&gt;Absolutely. AI is aggressively redefining the organic dividing lines of our tech communities. The old tribal boundaries — where we siloed ourselves strictly by language or stack — are giving way to a shared, collaborative push into the agentic era.&lt;/p&gt;

&lt;p&gt;The definition of an "AI engineer" isn't static, and it shouldn't be. Right now, keeping the product builders and the infrastructure scientists in the exact same room is a feature, not a bug. It's an inclusive, diverse context that is keeping all of us on the bleeding edge.&lt;/p&gt;

</description>
      <category>aie</category>
      <category>ai</category>
    </item>
    <item>
      <title>Pragmatism in an Age of Infinite Code and Unavoidable Bottlenecks</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Mon, 29 Jun 2026 16:05:56 +0000</pubDate>
      <link>https://dev.to/dailycontext/pragmatism-in-an-age-of-infinite-code-and-unavoidable-bottlenecks-1bkd</link>
      <guid>https://dev.to/dailycontext/pragmatism-in-an-age-of-infinite-code-and-unavoidable-bottlenecks-1bkd</guid>
      <description>&lt;p&gt;Leading into the &lt;a href="https://www.ai.engineer/worldsfair/2026" rel="noopener noreferrer"&gt;AI Engineer event in San Francisco&lt;/a&gt;, I’m looking forward to having my mind blown. That being said, I’m also compelled to think deeply about how we actually get things done in today’s software development landscape.&lt;/p&gt;

&lt;p&gt;There is competitive pressure to align on the principles of AI-driven software development. As developers and technical leaders, we are constantly trying to balance our pragmatism in the moment with our visions for the future.&lt;/p&gt;

&lt;p&gt;Throughout the history of software development, our collective immune system against hype has been our greatest asset. The safest, most reliable strategy has almost always been to not get swept up in the current fad. You let the early adopters bleed on the bleeding edge, you wait for the dust to settle, and then you adopt the tools that actually survive contact with production. Separating hype from reality is a critical skill for developers at all levels, and erring on the side of hype rejection has usually been smart money in the long run.&lt;/p&gt;

&lt;p&gt;In the AI revolution, separating real from hype is still valuable, but our heuristics are failing us, because the revolution is clearly here. Yet, even though there is obviously a massive amount of substance to AI-assisted development, the actual daily discourse is still hype-driven. It is an unhelpful, deafening mix of extreme utopian sentiment on one end and cynical over-dismissal on the other.&lt;/p&gt;

&lt;p&gt;Finding the signal in that noise requires a hard look at what has actually changed, and more importantly, what hasn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fallacy of Infinite Code
&lt;/h2&gt;

&lt;p&gt;AI has permanently rewritten the rules for how much software we can produce. In a purely quantitative sense, we now have the capacity to generate effectively infinite amounts of code. But if you’ve spent any time maintaining real-world systems, you know that raw code generation is rarely the true blocker to success.&lt;/p&gt;

&lt;p&gt;Actual value delivery is governed by choke points.&lt;/p&gt;

&lt;p&gt;These choke points are almost always driven by complex, human-centric factors: decision-makers needing consensus, cross-team collaboration, the friction of merging conflicting ideas, and the overriding need for architectural cohesion. Cohesion is that critical phase where the raw, sprawling net of potential features actually has to be distilled into a product that makes sense.&lt;br&gt;
In software, more is not necessarily more. In fact, unguided “more” usually just means accelerating your technical debt. We still need to deliver precise, focused, and intentional value.&lt;/p&gt;

&lt;p&gt;While AI is a massive help in attacking individual choke points — it can scaffold the boilerplate, write the tests, or debug the syntax — the bottleneck doesn't actually disappear. It just moves somewhere else. If we write code 10 times faster, the bottleneck shifts to code review. If we review faster using LLMs, the bottleneck shifts to product alignment and deployment infrastructure. The constraint always moves.&lt;/p&gt;

&lt;p&gt;Any development shop that still operates in a “traditional sense” is undeniably falling behind. Writing a spec the way we traditionally have is starting to feel completely redundant—that spec should simply be described directly to your agent of choice. We know there is a need to collaborate at a higher level on the problem at hand, allowing the individual developer to execute many cycles of development without the constant need for specification realignment.&lt;/p&gt;

&lt;p&gt;Realizing the value of infinite code in a competitive environment where the bar has been raised for everyone is a fundamentally unsolved problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The “Wait for the Next Model” Trap
&lt;/h2&gt;

&lt;p&gt;Because this bottleneck keeps shifting, it creates a specific kind of developer paralysis. Sometimes it feels like building tooling or workflows to resolve the bottlenecks we are seeing today is inherently just a stopgap.&lt;/p&gt;

&lt;p&gt;The nagging thought is always there: Why spend cycles optimizing this workflow or building around this friction? We could instead just wait for the models to get smarter. Give it six months, and the agents will just talk to each other and sort this out natively.&lt;br&gt;
This is the trap of anticipating the S-curve. A year or two ago, this logic actually held up. Some of yesterday’s bottlenecks genuinely weren’t worth solving because the next model intelligence leap made those local optimizations totally irrelevant. Building highly specific, complex wrappers around early LLMs was often a waste of time once the next foundational model dropped.&lt;/p&gt;

&lt;p&gt;But I think we are at a point where that logic is failing us because we’ve had enough time to collectively learn how we work with our core AI productivity tools. Things are settling down — for the moment. The bottlenecks we face today in software development and value delivery are inherently complicated on a human level, and they extend beyond the scope of near-term AI.&lt;/p&gt;

&lt;p&gt;Nothing short of Artificial Superintelligence (ASI) is going to overcome the natural, messy bottlenecks of real-world impact. Until an AI can sit in a room, navigate the political dynamics of a stakeholder meeting, understand the company’s runway, and empathize with the end-user’s actual day-to-day frustrations, these choke points remain tethered to human reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  We Don’t Need Autopilot, We Need Ergonomics
&lt;/h2&gt;

&lt;p&gt;Yes, we’ve automated some things away. Most things are still semi-autonomous at best, and if those things exist in a black box that surprises us too often and doesn’t hand things off in a usable way to move them along productively, we’re not actually beating our bottlenecks.&lt;/p&gt;

&lt;p&gt;Because of this reality, I don’t believe we are at the point where we resolve bottlenecks by taking our hands off the wheel. The prevailing sci-fi vision — that we just let the AI have full, unsupervised control of our computers as a magic bullet for productivity — misses the point of how good software gets built.&lt;br&gt;
Instead, the frontier of real productivity is about intuitive, human-in-the-loop workflows. It’s about ergonomics.&lt;/p&gt;

&lt;p&gt;We need environments and command centers where we can ergonomically understand the entire system at a glance. The goal isn’t to completely remove the human from the loop; it’s to make the loop so seamless that the human can operate at a fundamentally higher level of abstraction. We need tooling that helps reduce the cognitive burden of orchestrating developer agents, while still leaving us firmly in the driver’s seat. We need to be able to effortlessly send signals out, course-correct the AI, and manually clear the downstream blockers that the system can’t contextualize.&lt;/p&gt;

&lt;p&gt;When a developer can easily see what an agent is attempting, guide it with a single keystroke, and merge that work cohesively into a larger system architecture — that’s when the real value unlocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  On Skating Where the Puck is Going
&lt;/h2&gt;

&lt;p&gt;We don’t gain much waiting for massive, ground-up system design rethinking to save us from our current bottlenecks. The solution is resolving the friction where we see it, today, with the tools we have right now.&lt;/p&gt;

&lt;p&gt;Yes, the models will get better. Yes, the agents will get smarter, and our methods for getting things done will evolve from our successes and failures. But we have reached a spot in the current S-curve with enough maturity to make solving today’s friction highly valuable.&lt;/p&gt;

&lt;p&gt;Skate to where the puck is going, not where it has been (to quote Wayne Gretzky). It’s true in AI as well. We can absolutely skate to where the puck is going, but we don’t need to pretend the puck is in a whole different arena. Pragmatism in AI tooling today means accepting the incredible leverage we have right now, building the ergonomic, human-in-the-loop systems to actually harness it, and getting back to delivering precise, cohesive value.&lt;/p&gt;

&lt;p&gt;Today we are radically capable of solving yesterday’s problems with tremendous efficiency. However, the tug and pull between day-to-day iterative progress and step-change innovation is still generally a problem we have to manage ourselves. The most pragmatic thing you can do right now is stop waiting for the perfect autonomous system to clear your blockers and start orchestrating the tools you have. Build out your own command centers today — interfaces and workflows that give you high-level observability over your agents and complex workstreams. Invest in the tooling that keeps you effectively in the loop, rather than trying to engineer yourself out of it. The developers who win this cycle won’t be the ones with the smartest unsupervised agents; they will be the ones who build the most ergonomic systems to manage them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolving Our Outcomes
&lt;/h2&gt;

&lt;p&gt;It’s reasonable to build a human-in-the-loop productivity flow with the next phase in mind where the idea of “in the loop” is expected to keep changing. It’s reasonable to build for the future in this sense, but it is not practical to push off today’s problems in favor of waiting around to solve for a hypothetical future.&lt;/p&gt;

&lt;p&gt;Build for your people, your team, and your productive customers, not around and in spite of them. They’re more capable than ever. Recognizing this is how we push our outcomes forward.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aie</category>
      <category>productivity</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Meme Monday</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Mon, 29 Jun 2026 12:58:37 +0000</pubDate>
      <link>https://dev.to/ben/meme-monday-46a8</link>
      <guid>https://dev.to/ben/meme-monday-46a8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Meme Monday!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today's cover image comes from &lt;a href="https://dev.to/ben/meme-monday-1b8h"&gt;the last thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DEV is an inclusive space! Humor in poor taste will be downvoted by mods.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>jokes</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Meme Monday</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Mon, 22 Jun 2026 14:47:34 +0000</pubDate>
      <link>https://dev.to/ben/meme-monday-1b8h</link>
      <guid>https://dev.to/ben/meme-monday-1b8h</guid>
      <description>&lt;p&gt;&lt;strong&gt;Meme Monday!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today's cover image comes from &lt;a href="https://dev.to/ben/meme-monday-14pc"&gt;the last thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DEV is an inclusive space! Humor in poor taste will be downvoted by mods.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>jokes</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>How We Saved Big and Simplified Our Image Pipeline: Adopting bunny.net on DEV</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Tue, 16 Jun 2026 16:41:51 +0000</pubDate>
      <link>https://dev.to/devteam/how-we-saved-big-and-simplified-our-image-pipeline-adopting-bunnynet-on-dev-3d53</link>
      <guid>https://dev.to/devteam/how-we-saved-big-and-simplified-our-image-pipeline-adopting-bunnynet-on-dev-3d53</guid>
      <description>&lt;p&gt;Hey everyone, Ben here.&lt;/p&gt;

&lt;p&gt;If you’ve been following the journey of DEV and our open source project &lt;a href="https://github.com/forem/forem" rel="noopener noreferrer"&gt;Forem&lt;/a&gt;, you know we’ve always been obsessed with web performance. Way back in the day, I spoke at Codeland about how to make your website so fast it goes viral in Japan, diving into the mechanics of edge caching and how we kept our page loads nearly instant.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/lGQtUDMStnI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Our core philosophy has always been simple: keep the architecture as lean as possible, cache aggressively at the edge, and let the Rails monolith (Forem) focus on what it does best. For years, Fastly has handled our HTML edge caching brilliantly—most of your page requests never even have to touch our Puma servers, which keeps our RAM usage low and our response times in the milliseconds. Fastly continues to be how all the document content on DEV is served.&lt;/p&gt;

&lt;p&gt;But while edge-caching static HTML is a well-understood problem, user-uploaded media is a completely different beast. &lt;/p&gt;

&lt;p&gt;As DEV grew, we found ourselves drowning in images. Every post cover, user avatar, comment screenshot, and challenge banner is a high-res asset uploaded by our community. Serving billions of these images globally, while keeping page sizes lightweight, eventually led us into a silent scaling trap: a tangled, multi-CDN media pipeline, massive cloud egress fees, and eye-watering monthly bills.&lt;/p&gt;

&lt;p&gt;Here is the story of how we ended the multi-CDN chaos, simplified our media architecture, saved a small fortune, and used edge scripting to build a smarter, faster image-serving pipeline with &lt;a href="https://bunny.net" rel="noopener noreferrer"&gt;bunny.net&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Chaos of Multi-CDN and the Billing Reality Check
&lt;/h2&gt;

&lt;p&gt;To understand why we made the switch, you have to look at what our image pipeline used to look like. &lt;/p&gt;

&lt;p&gt;For a long time, our media stack was a bit of a patchwork. We had different CDNs handling different parts of the platform, an image proxying service for dynamic resizing, and raw assets sitting in cloud storage (like AWS S3). &lt;/p&gt;

&lt;p&gt;When a user uploads a 10MB JPEG as an article cover, our Rails app doesn't pre-process it into dozens of different dimensions. Instead, we rely on on-the-fly image transformation. In theory, this is great: the browser requests &lt;code&gt;image.jpg?width=800&lt;/code&gt;, and a dynamic image optimizer resizes it, converts it to WebP or AVIF, and serves it.&lt;/p&gt;

&lt;p&gt;In practice, the economics and mechanics of this setup at scale are brutal, especially when you factor in the realities of modern web traffic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Scraper &amp;amp; Traffic Tax:&lt;/strong&gt; On the open web, you aren't just serving human users. You are constantly being hit by RSS readers, search crawlers, and high-frequency scrapers. Traditional setups simply weren't smart enough to handle this gracefully. A wave of aggressive scrapers requesting un-cached variations or bypassing standard query parameters would force our pipeline to repeatedly re-fetch and re-process assets, sending computing costs into the stratosphere. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Egress Fees:&lt;/strong&gt; Every single time an image optimizer had to fetch a raw image from our cloud storage origin because of a cache miss (often induced by the traffic patterns mentioned above), we paid steep cloud egress fees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformation Pricing:&lt;/strong&gt; Many premium image CDNs charge "per thousand images processed" or utilize complex, punitive usage tiers. When you have millions of active posts and users scrolling feeds with hundreds of custom-sized avatars, those transformation counts skyrocket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-CDN Friction:&lt;/strong&gt; Running separate providers for HTML caching and image delivery/optimization created massive operational overhead. We had complex header configurations, CORS issues, and routing rules scattered across different YAML files and dashboards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our media bills were ballooning, it was incredibly expensive, and we were spending way too much time debugging why our pipeline wasn't smart enough to handle volatile traffic spikes smoothly. We needed a solution that was fast, reliable, highly configurable, and above all, economically sustainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Hopped Over to bunny.net
&lt;/h2&gt;

&lt;p&gt;I’ve actually been using bunny.net for years across many of my personal projects. Whether spinning up a quick side application or testing out a new concept, I always found myself returning to it because it is an incredibly well-designed platform with sensible, intuitive products. It lacks the dense, enterprise bloat of traditional cloud vendors; instead, it provides clean developer ergonomics that just work. Because of that first-hand experience, I knew it was a platform we could trust to scale seamlessly with DEV.&lt;/p&gt;

&lt;p&gt;What really sold us for Forem wasn't just the raw bandwidth savings (though slashing our bandwidth bills to a fraction of what premium enterprise CDNs charge was a massive win). It was how beautifully their product ecosystem handled our specific architectural pain points through the combination of &lt;strong&gt;&lt;a href="https://docs.bunny.net/optimizer&amp;amp;sa=D&amp;amp;source=docs&amp;amp;ust=1781024983671285&amp;amp;usg=AOvVaw2Y7n05XU3d31p19gJMiySy" rel="noopener noreferrer"&gt;Bunny Optimizer&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://docs.bunny.net/scripting&amp;amp;sa=D&amp;amp;source=docs&amp;amp;ust=1781024983671402&amp;amp;usg=AOvVaw3kuoHo97Y2pAuGGaSS0qnR" rel="noopener noreferrer"&gt;Edge Scripting&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Bunny Optimizer and Perma-Cache
&lt;/h3&gt;

&lt;p&gt;Bunny Optimizer acts as a fully managed, dynamic image transformation API. We could easily plug it in, append simple URL query parameters (like &lt;code&gt;?width=600&amp;amp;height=300&amp;amp;crop=1:1&lt;/code&gt;), and let Optimizer handle the resizing, cropping, and automatic compression on-the-fly. It automatically negotiates next-gen formats like WebP or AVIF based on the browser's &lt;code&gt;Accept&lt;/code&gt; headers, reducing file sizes by up to 80% without any visible quality loss.&lt;/p&gt;

&lt;p&gt;But the real magic ingredient—and our ultimate weapon against scraper traffic—is &lt;strong&gt;Perma-Cache&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Normally, when a CDN edge server evicts an infrequently accessed image variant, the next request has to go all the way back to the origin (our cloud storage) to fetch and re-optimize it, triggering more egress fees. Perma-Cache solves this by permanently replicating the optimized image variants to Bunny Storage. &lt;/p&gt;

&lt;p&gt;Once an image is processed once, it is stored at the edge forever. It never has to hit our AWS origin again, shielding our backend from erratic traffic and virtually eliminated our cloud storage egress fees overnight.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Edge Scripting: TypeScript-Native Control
&lt;/h3&gt;

&lt;p&gt;While Bunny Optimizer gave us the raw power to resize images, we needed fine-grained control over how we served them. We didn't want to pollute our Rails views with complicated URL-building logic, and we wanted to prevent users (or bots) from downloading massive raw images.&lt;/p&gt;

&lt;p&gt;This is where Edge Scripting came in. &lt;/p&gt;

&lt;p&gt;Built on Deno and V8, Edge Scripting runs JavaScript and TypeScript directly at the edge, allowing us to write lightweight, type-safe middleware that executes in milliseconds. It completely replaced the need for custom image proxies or complex Rails controller routing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Under the Hood: Forem’s Pluggable Images::Optimizer Service
&lt;/h2&gt;

&lt;p&gt;If you look into Forem's codebase, you’ll see that we’ve always designed our image pipeline to be pluggable. We didn't want to hardcode our views to use a specific CDN's query parameters. If a template wants to render a post cover image, it calls a unified helper that delegates to our &lt;code&gt;Images::Optimizer&lt;/code&gt; service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;# app/views/layouts/application.html.erb
&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="no"&gt;Images&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Optimizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;General&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;favicon_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;width: &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;app/services/images/optimizer.rb&lt;/code&gt;, we use a simple strategy pattern. The &lt;code&gt;Optimizer&lt;/code&gt; class acts as a router that maps standardized parameters (like &lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, &lt;code&gt;fit&lt;/code&gt;, &lt;code&gt;gravity&lt;/code&gt;) to the specific URL format required by the active CDN provider. &lt;/p&gt;

&lt;p&gt;Historically, Forem has supported providers like Fastly, Cloudflare, and Cloudinary and adding bunny.net was incredibly straightforward. Here is a look at how our Rails service handles this multi-CDN routing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/services/images/optimizer.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Images&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Optimizer&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

      &lt;span class="c1"&gt;# Select the provider strategy based on our environment configuration&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:bunny&lt;/span&gt;
        &lt;span class="no"&gt;BunnyProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:cloudflare&lt;/span&gt;
        &lt;span class="no"&gt;CloudflareProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:fastly&lt;/span&gt;
        &lt;span class="no"&gt;FastlyProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provider&lt;/span&gt;
      &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"IMAGE_OPTIMIZATION_PROVIDER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"bunny"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_sym&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each provider implements its own URL rewriting strategy. For example, our bunny.net provider simply builds standard query strings that Bunny Optimizer parses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/services/images/bunny_provider.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Images&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BunnyProvider&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
      &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;query_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
      &lt;span class="n"&gt;query_params&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"width=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:width&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:width&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;query_params&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"height=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:height&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:height&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;query_params&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"crop=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:crop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:crop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;query_params&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"auto=format"&lt;/span&gt;

      &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;amp;"&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;amp;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This decoupled architecture is fantastic for an open-source project like Forem. Different self-hosted communities can configure their own CDN of choice by simply changing the &lt;code&gt;IMAGE_OPTIMIZATION_PROVIDER&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;However, while the Rails app generates these optimized URLs, we ran into an interesting operational challenge: what happens when a template forgets to pass a width parameter, or a legacy post contains raw external URLs? &lt;/p&gt;

&lt;p&gt;If we relied only on Rails-side URL building, any fallback or unparsed URL would still trigger a heavy, unoptimized image load. This is where our Edge Scripting strategy stepped in—to act as a global safety net right at the network boundary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Highlight: Smart Downsizing at the Edge
&lt;/h2&gt;

&lt;p&gt;With Edge Scripting, we can intercept image requests right at the CDN layer and apply custom business logic before the request even reaches the optimizer or storage. &lt;/p&gt;

&lt;p&gt;For example, we wanted to ensure that user profile avatars and feed thumbnails are never served larger than they actually need to be, regardless of what the original upload was or what query parameters were requested. If a client requests a raw, un-optimized avatar URL, our edge script automatically intercepts it, checks the context, and rewrites the request to enforce a strict maximum width and apply WebP compression.&lt;/p&gt;

&lt;p&gt;Here's a simplified example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A lightweight middleware script running on bunny.net's Edge&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Intercept requests to our user-uploaded uploads path&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/uploads/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAvatar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/avatars/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isThumbnail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/thumbnails/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if the request already has optimization parameters&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAvatar&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Dedicatedly downsize all avatar requests to a max of 150px&lt;/span&gt;
      &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;150&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;150&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1:1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isThumbnail&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Enforce a strict mobile-friendly limit on thumbnails&lt;/span&gt;
      &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;400&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Ensure automatic next-gen format negotiation (WebP/AVIF) is active&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;format&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch the optimized asset from bunny.net's CDN pipeline&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is incredibly powerful because it offloads the "computational thinking" of image delivery entirely to the edge. Our Rails application doesn't have to keep track of responsive image breakpoints or generate heavy, complex markup. We just request the logical asset URL, and our edge script dynamically handles the rest based on client headers and context.&lt;/p&gt;

&lt;p&gt;Even better, we’ve integrated this into our standard development workflows. We use GitHub Actions combined with fine-grained personal access tokens to manage and deploy these edge scripts automatically. When we want to adjust our optimization rules or add support for a new layout—like optimizing billboard images or adjusting resolutions on challenge pages—we just push a commit, our CI runs, and the new edge logic is live globally in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Graceful Failures: Smart Fallbacks Over Plain Broken Images
&lt;/h2&gt;

&lt;p&gt;Beyond routing and sizing, running code at the edge unlocked a massive UX victory: the ability to handle missing or broken assets gracefully. &lt;/p&gt;

&lt;p&gt;In a massive community ecosystem, edge cases happen. A user might delete an external image they linked to, an old upload path might break during a migration, or a malformed request could slide through. Traditionally, when an image fails to load or returns a 404/500, the browser drops a jarring, ugly "broken image" icon that disrupts the layout and makes the entire site look broken.&lt;/p&gt;

&lt;p&gt;With Edge Scripting, we can catch these failures mid-flight. If our origin or storage returns an error status code, the edge script intercepts the response and seamlessly rewrites it to serve a beautifully styled, custom placeholder image that says &lt;em&gt;"Image not available"&lt;/em&gt; or matches our UI theme. &lt;/p&gt;

&lt;p&gt;Instead of writing complex, heavy JavaScript event listeners (&lt;code&gt;onError&lt;/code&gt;) into every single &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag across the Rails application, we handle it natively at the network layer. The application layer never has to think about fallback logic, and our users get a consistent, unbroken visual experience no matter what happens behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future considerations
&lt;/h2&gt;

&lt;p&gt;Stabilizing and optimizing our image pipeline was just phase one. As we look ahead to how DEV and Forem will continue to evolve, video is the next logical horizon. &lt;/p&gt;

&lt;p&gt;Video delivery is notoriously complex—requiring adaptive bitrate streaming (HLS/DASH), multi-resolution transcoding, specialized storage, and optimized video players. In legacy architectures, this usually means spinning up another fragmented set of expensive third-party video processors and complex integrations.&lt;/p&gt;

&lt;p&gt;Given our success with their media infrastructure, bunny.net is our definitive first choice for how we are thinking about video moving forward. Their unified platform approach extends directly into video streaming with products that match the same sensible, developer-first philosophy as their image optimizer. Because we can trust their infrastructure to scale predictably without predatory data transfer costs, expanding our edge architecture to handle next-generation rich media feels like a natural progression rather than a daunting infrastructure overhaul.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;As developers, we often focus on optimizing our database queries, refactoring Ruby code, or fine-tuning our server configurations. But sometimes, the biggest wins are sitting right there in your network tab. &lt;/p&gt;

&lt;p&gt;Egress fees and bloated media delivery are a silent tax on growing platforms. By moving to an edge-native, developer-friendly platform like bunny.net, we were able to simplify our architecture, speed up our page loads, and save a lot of money in the process. &lt;/p&gt;

&lt;p&gt;If you’re running a media-heavy platform or building open-source community software like Forem, do yourself a favor: look closely at your CDN bills, check your cloud storage egress, and see if you can offload some of that weight to a platform built to grow with you. Your budget (and your users) will thank you.&lt;/p&gt;

&lt;p&gt;Happy coding ❤️&lt;/p&gt;

</description>
      <category>performance</category>
      <category>webdev</category>
      <category>design</category>
      <category>bunny</category>
    </item>
    <item>
      <title>Meme Monday</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:10:18 +0000</pubDate>
      <link>https://dev.to/ben/meme-monday-14pc</link>
      <guid>https://dev.to/ben/meme-monday-14pc</guid>
      <description>&lt;p&gt;&lt;strong&gt;Meme Monday!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today's cover image comes from &lt;a href="https://dev.to/ben/meme-monday-1m9f"&gt;the last thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DEV is an inclusive space! Humor in poor taste will be downvoted by mods.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>jokes</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Meme Monday</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Mon, 08 Jun 2026 12:39:59 +0000</pubDate>
      <link>https://dev.to/ben/meme-monday-1m9f</link>
      <guid>https://dev.to/ben/meme-monday-1m9f</guid>
      <description>&lt;p&gt;&lt;strong&gt;Meme Monday!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today's cover image comes from &lt;a href="https://dev.to/ben/meme-monday-25la"&gt;the last thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DEV is an inclusive space! Humor in poor taste will be downvoted by mods.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>jokes</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Every tool seems to have a coding agent horned in these days..... I don't think that makes sense.</title>
      <dc:creator>Ben Halpern</dc:creator>
      <pubDate>Wed, 03 Jun 2026 13:46:51 +0000</pubDate>
      <link>https://dev.to/ben/every-tool-seems-to-have-a-coding-agent-horned-in-these-days-i-dont-think-that-makes-sense-3db</link>
      <guid>https://dev.to/ben/every-tool-seems-to-have-a-coding-agent-horned-in-these-days-i-dont-think-that-makes-sense-3db</guid>
      <description></description>
      <category>agents</category>
      <category>ai</category>
      <category>discuss</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
