<?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: Franklyn Nmesoma</title>
    <description>The latest articles on DEV Community by Franklyn Nmesoma (@franklyn_nmesoma).</description>
    <link>https://dev.to/franklyn_nmesoma</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%2F3973027%2Fda7e7825-8f16-4d0b-a392-c5e5486ada65.png</url>
      <title>DEV Community: Franklyn Nmesoma</title>
      <link>https://dev.to/franklyn_nmesoma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/franklyn_nmesoma"/>
    <language>en</language>
    <item>
      <title>Building Production AI Systems (Part 3)</title>
      <dc:creator>Franklyn Nmesoma</dc:creator>
      <pubDate>Fri, 24 Jul 2026 05:45:00 +0000</pubDate>
      <link>https://dev.to/franklyn_nmesoma/building-production-ai-systems-part-3-bnf</link>
      <guid>https://dev.to/franklyn_nmesoma/building-production-ai-systems-part-3-bnf</guid>
      <description>&lt;p&gt;Running OpenRouter in Production: What Breaks, What Works, and What I’d Do Differently&lt;/p&gt;

&lt;p&gt;Getting an LLM to respond to your first prompt is easy.&lt;/p&gt;

&lt;p&gt;Keeping it reliable in production?&lt;/p&gt;

&lt;p&gt;That’s where things become interesting.&lt;/p&gt;

&lt;p&gt;One thing I’ve learned building software is that users don’t care whose fault it is when something breaks.&lt;/p&gt;

&lt;p&gt;If your AI feature fails because OpenAI is down…&lt;/p&gt;

&lt;p&gt;Or Claude is rate-limited…&lt;/p&gt;

&lt;p&gt;Or your network connection decides to disappear for five seconds…&lt;/p&gt;

&lt;p&gt;Your users won’t blame the provider.&lt;/p&gt;

&lt;p&gt;They’ll blame your application.&lt;/p&gt;

&lt;p&gt;That’s why integrating an AI model isn’t enough.&lt;/p&gt;

&lt;p&gt;You need to engineer for failure, lets talk about how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error handling should be boring
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages of OpenRouter is that it standardizes responses from different providers.&lt;/p&gt;

&lt;p&gt;Without it, you often end up writing provider-specific error handling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```typescript
if (provider === “openai”) {
…
}

if (provider === “anthropic”) {
…
}

if (provider === “google”) {
…
}
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gets messy very quickly.&lt;/p&gt;

&lt;p&gt;With OpenRouter, your application talks to one API contract.&lt;/p&gt;

&lt;p&gt;Which means your error handling becomes predictable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```typescript
try {
const response = await client.chat.completions.create({…});
} catch (error) {
logger.error(error);
}
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;Your code shouldn’t care which provider failed.&lt;/p&gt;

&lt;p&gt;It should care how your application responds when one does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logging is your best friend
&lt;/h2&gt;

&lt;p&gt;One mistake I see quite often is developers only logging the error message.&lt;/p&gt;

&lt;p&gt;That’s rarely enough.&lt;/p&gt;

&lt;p&gt;When something fails in production, you want context.&lt;/p&gt;

&lt;p&gt;Log things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model that was used.&lt;/li&gt;
&lt;li&gt;Request duration.&lt;/li&gt;
&lt;li&gt;Token usage.&lt;/li&gt;
&lt;li&gt;HTTP status code.&lt;/li&gt;
&lt;li&gt;Whether a fallback model was triggered.&lt;/li&gt;
&lt;li&gt;The user making the request (if appropriate).&lt;/li&gt;
&lt;li&gt;Timestamp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single log entry should tell you the complete story without having to reproduce the issue.&lt;/p&gt;

&lt;p&gt;Future you will appreciate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability beats guessing
&lt;/h2&gt;

&lt;p&gt;Imagine a customer reports:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The AI stopped working around 2 PM.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without observability, you’re guessing.&lt;/p&gt;

&lt;p&gt;Was it your backend?&lt;/p&gt;

&lt;p&gt;OpenRouter?&lt;/p&gt;

&lt;p&gt;Claude?&lt;/p&gt;

&lt;p&gt;Gemini?&lt;/p&gt;

&lt;p&gt;A timeout?&lt;/p&gt;

&lt;p&gt;A deployment?&lt;/p&gt;

&lt;p&gt;Good observability removes the guesswork.&lt;/p&gt;

&lt;p&gt;OpenRouter provides request tracking that allows you to match requests from your application with what happened inside their dashboard.&lt;/p&gt;

&lt;p&gt;Instead of spending hours wondering where things went wrong, you can trace a single request from your backend logs all the way through the gateway.&lt;/p&gt;

&lt;p&gt;That’s incredibly valuable once real users are involved.&lt;/p&gt;

&lt;p&gt;Request IDs are underrated&lt;/p&gt;

&lt;p&gt;Every request should have an identity.&lt;/p&gt;

&lt;p&gt;Whether you’re using OpenRouter’s request identifiers or generating your own correlation IDs, always include them in your logs.&lt;/p&gt;

&lt;p&gt;Imagine one user reports:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My response never arrived.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without a request ID, you’re searching through thousands of log entries.&lt;/p&gt;

&lt;p&gt;With one, you can immediately trace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when the request started,&lt;/li&gt;
&lt;li&gt;which model processed it,&lt;/li&gt;
&lt;li&gt;whether retries occurred,&lt;/li&gt;
&lt;li&gt;whether fallbacks were triggered,&lt;/li&gt;
&lt;li&gt;and how long everything took.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production debugging becomes dramatically easier.&lt;/p&gt;

&lt;p&gt;Streaming isn’t always as straightforward as it looks&lt;/p&gt;

&lt;p&gt;Streaming responses make AI applications feel much faster.&lt;/p&gt;

&lt;p&gt;Instead of waiting ten seconds for a complete answer, users start seeing words appear almost immediately.&lt;/p&gt;

&lt;p&gt;Great user experience.&lt;/p&gt;

&lt;p&gt;But there’s a catch.&lt;/p&gt;

&lt;p&gt;Not every provider streams responses in exactly the same way.&lt;/p&gt;

&lt;p&gt;Although OpenRouter normalizes much of this behavior, you’ll still want to build frontend parsers that are resilient.&lt;/p&gt;

&lt;p&gt;Don’t assume every chunk arrives perfectly.&lt;/p&gt;

&lt;p&gt;Don’t assume every event contains text.&lt;/p&gt;

&lt;p&gt;Don’t assume the connection won’t terminate unexpectedly.&lt;/p&gt;

&lt;p&gt;Your frontend should gracefully handle incomplete streams instead of crashing halfway through a response.&lt;/p&gt;

&lt;p&gt;Timeouts are not optional&lt;/p&gt;

&lt;p&gt;One of the easiest ways to create a poor user experience is to let requests hang forever.&lt;/p&gt;

&lt;p&gt;Sometimes providers are slow.&lt;/p&gt;

&lt;p&gt;Sometimes networks are unreliable.&lt;/p&gt;

&lt;p&gt;Sometimes things simply break.&lt;/p&gt;

&lt;p&gt;Your application should know when to stop waiting.&lt;/p&gt;

&lt;p&gt;Set reasonable timeout limits.&lt;/p&gt;

&lt;p&gt;If a request takes too long, cancel it.&lt;/p&gt;

&lt;p&gt;Your users would rather receive a helpful message after fifteen seconds than stare at an infinite loading spinner.&lt;/p&gt;

&lt;p&gt;An application that knows when to give up usually feels faster than one that waits forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Graceful degradation
&lt;/h2&gt;

&lt;p&gt;This is one of my favourite engineering principles.&lt;/p&gt;

&lt;p&gt;Just because one provider fails doesn’t mean your feature should disappear completely.&lt;/p&gt;

&lt;p&gt;Imagine your primary reasoning model becomes unavailable.&lt;/p&gt;

&lt;p&gt;Instead of returning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something went wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why not automatically switch to a faster fallback model?&lt;/p&gt;

&lt;p&gt;Maybe the answer isn’t quite as detailed.&lt;/p&gt;

&lt;p&gt;Maybe it isn’t as creative.&lt;/p&gt;

&lt;p&gt;But your user still gets a response.&lt;/p&gt;

&lt;p&gt;That’s infinitely better than an error screen.&lt;/p&gt;

&lt;p&gt;Graceful degradation isn’t about perfection.&lt;/p&gt;

&lt;p&gt;It’s about maintaining functionality when perfection isn’t possible.&lt;/p&gt;

&lt;p&gt;Build retries carefully&lt;/p&gt;

&lt;p&gt;Retries sound simple.&lt;/p&gt;

&lt;p&gt;Until they aren’t.&lt;/p&gt;

&lt;p&gt;If a request fails because of a temporary network issue, retrying makes sense.&lt;/p&gt;

&lt;p&gt;If it fails because the provider is overloaded, retrying after a short delay might work.&lt;/p&gt;

&lt;p&gt;But if the request is invalid?&lt;/p&gt;

&lt;p&gt;Retrying it five times won’t magically fix bad input.&lt;/p&gt;

&lt;p&gt;A good retry strategy should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retry only transient failures.&lt;/li&gt;
&lt;li&gt;Use exponential backoff instead of immediate retries.&lt;/li&gt;
&lt;li&gt;Set a maximum retry limit.&lt;/li&gt;
&lt;li&gt;Log every retry attempt.&lt;/li&gt;
&lt;li&gt;Stop retrying when success is unlikely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Retries should improve reliability.&lt;/p&gt;

&lt;p&gt;Not create more traffic.&lt;/p&gt;

&lt;p&gt;Final thoughts&lt;/p&gt;

&lt;p&gt;One thing AI development has taught me is that choosing the right model is only a small part of building reliable applications.&lt;/p&gt;

&lt;p&gt;The real challenge is designing systems that continue working when models slow down, providers become unavailable, or networks become unreliable.&lt;/p&gt;

&lt;p&gt;Because eventually…&lt;/p&gt;

&lt;p&gt;Something will fail.&lt;/p&gt;

&lt;p&gt;The question isn’t whether it happens.&lt;/p&gt;

&lt;p&gt;The question is whether your users notice.&lt;/p&gt;

&lt;p&gt;If they don’t, you’ve probably built your system well.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoying the series? Let me know in the comments.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ooh and do not forget to connect with me so you do not miss out on the next parts of the series.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building Production AI Systems(Part 2)</title>
      <dc:creator>Franklyn Nmesoma</dc:creator>
      <pubDate>Wed, 08 Jul 2026 13:15:00 +0000</pubDate>
      <link>https://dev.to/franklyn_nmesoma/building-production-ai-systemspart-2-224c</link>
      <guid>https://dev.to/franklyn_nmesoma/building-production-ai-systemspart-2-224c</guid>
      <description>&lt;h2&gt;
  
  
  Integrating OpenRouter into a Real Application
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is Part 2 of a five-part series on building production-ready AI applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the previous article, I talked about why I stopped juggling multiple AI SDKs and settled on OpenRouter as the abstraction layer between my applications and different LLM providers.&lt;/p&gt;

&lt;p&gt;Now comes the fun part.&lt;/p&gt;

&lt;p&gt;The actual integration.&lt;/p&gt;

&lt;p&gt;If you've ever integrated the OpenAI SDK before, then you'll feel right at home because, surprisingly, not much changes.&lt;/p&gt;

&lt;p&gt;And honestly, that's one of my favorite things about OpenRouter.&lt;/p&gt;

&lt;p&gt;You don't install another SDK.&lt;/p&gt;

&lt;p&gt;You don't learn another API.&lt;/p&gt;

&lt;p&gt;You don't rewrite your application.&lt;/p&gt;

&lt;p&gt;You simply point your existing client somewhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set up your client
&lt;/h2&gt;

&lt;p&gt;If you're already using the official OpenAI SDK, your client initialization changes very little.&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;//typescript&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&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;client&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;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://openrouter.ai/api/v1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Instead of pointing to OpenAI's endpoint, you're pointing to OpenRouter's gateway.&lt;/p&gt;

&lt;p&gt;From your application's perspective, nothing else really changes.&lt;/p&gt;

&lt;p&gt;And that's exactly the point.&lt;/p&gt;

&lt;p&gt;OpenRouter doesn't try to replace the OpenAI API.&lt;/p&gt;

&lt;p&gt;It implements it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Base URL matters
&lt;/h2&gt;

&lt;p&gt;At first glance, changing a single URL doesn't seem like much.&lt;/p&gt;

&lt;p&gt;But that one line completely changes what your application is capable of.&lt;/p&gt;

&lt;p&gt;Yesterday, your requests could only reach OpenAI.&lt;/p&gt;

&lt;p&gt;Today, the same client can talk to Claude, Gemini, Llama, DeepSeek, Mistral, Qwen, and hundreds of other models without installing another dependency.&lt;/p&gt;

&lt;p&gt;That's the power of abstraction.&lt;/p&gt;

&lt;p&gt;Your application doesn't care where the response comes from.&lt;/p&gt;

&lt;p&gt;It only cares that it receives one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't ignore the headers
&lt;/h2&gt;

&lt;p&gt;One thing many developers skip is the optional headers OpenRouter recommends.&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;//typescript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&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;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://openrouter.ai/api/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;defaultHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HTTP-Referer&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="s2"&gt;https://yourapp.com&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="s2"&gt;X-Title&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="s2"&gt;My AI Application&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These headers aren't required for your application to work.&lt;/p&gt;

&lt;p&gt;However, they make a huge difference when you're monitoring usage inside the OpenRouter dashboard.&lt;/p&gt;

&lt;p&gt;Think of them as metadata.&lt;/p&gt;

&lt;p&gt;Instead of seeing anonymous API traffic, you'll know exactly which application generated which requests.&lt;/p&gt;

&lt;p&gt;If you're managing multiple projects, you'll thank yourself later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model switching becomes configuration
&lt;/h2&gt;

&lt;p&gt;Here's where OpenRouter really starts to shine.&lt;/p&gt;

&lt;p&gt;Normally, switching providers means changing SDKs.&lt;/p&gt;

&lt;p&gt;Sometimes it means changing request payloads.&lt;/p&gt;

&lt;p&gt;Occasionally it means rewriting parts of your application altogether.&lt;/p&gt;

&lt;p&gt;With OpenRouter, switching models is often as simple as changing one string.&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;//typescript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;completion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MODEL_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;messages&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;Yesterday:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MODEL_NAME=openai/gpt-4o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MODEL_NAME=anthropic/claude-3.7-sonnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tomorrow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MODEL_NAME=deepseek/deepseek-r1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No deployment.&lt;/p&gt;

&lt;p&gt;No new SDK.&lt;/p&gt;

&lt;p&gt;No wrapper functions.&lt;/p&gt;

&lt;p&gt;Just configuration.&lt;/p&gt;

&lt;p&gt;That's a huge win for maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happens after you send a request?
&lt;/h2&gt;

&lt;p&gt;This is probably the most overlooked part of OpenRouter.&lt;/p&gt;

&lt;p&gt;When your application sends a request, it doesn't simply forward the payload.&lt;/p&gt;

&lt;p&gt;It interprets it.&lt;/p&gt;

&lt;p&gt;Your application sends a standard OpenAI-compatible request.&lt;/p&gt;

&lt;p&gt;OpenRouter receives it.&lt;/p&gt;

&lt;p&gt;Then it translates that request into whatever format the target provider expects.&lt;/p&gt;

&lt;p&gt;Claude has its own conventions.&lt;/p&gt;

&lt;p&gt;Gemini has slightly different expectations.&lt;/p&gt;

&lt;p&gt;Reasoning models expose different parameters.&lt;/p&gt;

&lt;p&gt;OpenRouter smooths over those differences before forwarding the request upstream.&lt;/p&gt;

&lt;p&gt;When the provider responds, OpenRouter performs the reverse operation.&lt;/p&gt;

&lt;p&gt;It normalizes the response back into the OpenAI format your application already understands.&lt;/p&gt;

&lt;p&gt;From your code's perspective, every provider behaves like OpenAI.&lt;/p&gt;

&lt;p&gt;That's why your application code stays clean while still supporting multiple providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building for failure
&lt;/h2&gt;

&lt;p&gt;Production systems fail.&lt;/p&gt;

&lt;p&gt;Rate limits happen.&lt;/p&gt;

&lt;p&gt;Providers experience outages.&lt;/p&gt;

&lt;p&gt;Network latency spikes.&lt;/p&gt;

&lt;p&gt;The question isn't whether they'll happen.&lt;/p&gt;

&lt;p&gt;It's whether your application is prepared when they do.&lt;/p&gt;

&lt;p&gt;One of my favorite OpenRouter features is model fallbacks.&lt;/p&gt;

&lt;p&gt;Instead of depending on a single provider, you can prioritize multiple models.&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;//typescript&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anthropic/claude-3-opus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anthropic/claude-3-opus&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="s2"&gt;google/gemini-pro&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="s2"&gt;meta-llama/llama-3-70b&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Imagine Claude temporarily returns a &lt;strong&gt;429 Too Many Requests&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without fallbacks?&lt;/p&gt;

&lt;p&gt;Your user sees an error.&lt;/p&gt;

&lt;p&gt;With fallbacks?&lt;/p&gt;

&lt;p&gt;OpenRouter automatically retries using the next available model in your priority list.&lt;/p&gt;

&lt;p&gt;Most users won't even notice anything happened.&lt;/p&gt;

&lt;p&gt;That's the kind of resilience users expect but rarely appreciate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;One of the biggest lessons I've learned building AI-powered applications is that your application shouldn't care which model answered the request.&lt;/p&gt;

&lt;p&gt;It should care that the request succeeded.&lt;/p&gt;

&lt;p&gt;The more your business logic depends on provider-specific behavior, the harder your code becomes to maintain.&lt;/p&gt;

&lt;p&gt;OpenRouter flips that relationship.&lt;/p&gt;

&lt;p&gt;Providers become interchangeable.&lt;/p&gt;

&lt;p&gt;Your application stays consistent.&lt;/p&gt;

&lt;p&gt;And as new models continue to emerge almost every week, I think that's an architectural decision that will only become more valuable over time.&lt;/p&gt;

&lt;p&gt;If you found this helpful, check out part 1, leave a comment and follow me so you don't miss the next parts of the series, coming soon.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>llm</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building Production AI Systems(Part 1)</title>
      <dc:creator>Franklyn Nmesoma</dc:creator>
      <pubDate>Sat, 04 Jul 2026 13:15:00 +0000</pubDate>
      <link>https://dev.to/franklyn_nmesoma/building-production-ai-systemspart-1-10gm</link>
      <guid>https://dev.to/franklyn_nmesoma/building-production-ai-systemspart-1-10gm</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;OpenRouter isn't just another AI gateway. It's an architectural decision.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is Part 1 of a five-part series on building production-ready AI applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A few months ago, if you wanted to experiment with multiple LLM providers in the same application, you'd probably end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;npm install openai&lt;/em&gt;&lt;br&gt;
&lt;em&gt;npm install @anthropic-ai/sdk&lt;/em&gt;&lt;br&gt;
&lt;em&gt;npm install @google/generative-ai&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fast forward a few weeks and your code-base starts looking… interesting.&lt;/p&gt;

&lt;p&gt;One SDK expects messages in one format.&lt;/p&gt;

&lt;p&gt;Another throws completely different error objects.&lt;/p&gt;

&lt;p&gt;One provider supports streaming differently.&lt;/p&gt;

&lt;p&gt;Another requires its own authentication flow.&lt;/p&gt;

&lt;p&gt;Before long, you've written a wrapper around a wrapper that's wrapping yet another SDK just so your application can ask a chat-bot a simple question.&lt;/p&gt;

&lt;p&gt;I've been there.&lt;/p&gt;

&lt;p&gt;And honestly, none of that complexity adds value to your product.&lt;/p&gt;

&lt;p&gt;Your users don't care whether the response came from GPT-4o, Claude Sonnet, Gemini, DeepSeek, or Llama.&lt;/p&gt;

&lt;p&gt;They care that the response is fast, reliable, and useful.&lt;/p&gt;

&lt;p&gt;That's what eventually led me to OpenRouter.&lt;/p&gt;

&lt;p&gt;At first, I assumed it was just another API gateway sitting between my application and a bunch of AI providers.&lt;/p&gt;

&lt;p&gt;After using it in production, I realized it solves a much bigger problem.&lt;/p&gt;

&lt;p&gt;It lets you stop thinking about providers and start thinking about capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The fragmented client&amp;nbsp;problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the biggest mistakes teams make when integrating AI is tightly coupling their application to a single provider.&lt;/p&gt;

&lt;p&gt;It usually starts innocently.&lt;/p&gt;

&lt;p&gt;Maybe you're building with OpenAI because it's the easiest place to begin.&lt;/p&gt;

&lt;p&gt;A few months later, Claude becomes better at long-form reasoning.&lt;/p&gt;

&lt;p&gt;Then Gemini introduces a feature you want.&lt;/p&gt;

&lt;p&gt;Then an open-weight model suddenly becomes good enough while costing a fraction of the price.&lt;/p&gt;

&lt;p&gt;Now you have a problem.&lt;/p&gt;

&lt;p&gt;Your application isn't talking to "an LLM."&lt;/p&gt;

&lt;p&gt;It's talking to three completely different SDKs.&lt;/p&gt;

&lt;p&gt;Three authentication methods.&lt;/p&gt;

&lt;p&gt;Three different request formats.&lt;/p&gt;

&lt;p&gt;Three different response objects.&lt;/p&gt;

&lt;p&gt;Three different ways of handling errors.&lt;/p&gt;

&lt;p&gt;Suddenly, changing models isn't a product decision anymore.&lt;/p&gt;

&lt;p&gt;It's a refactoring exercise.&lt;/p&gt;

&lt;p&gt;That's exactly the problem OpenRouter solves.&lt;/p&gt;

&lt;p&gt;Instead of installing a separate SDK for every provider, OpenRouter becomes a single entry point for every model your application needs.&lt;/p&gt;

&lt;p&gt;To your application, it behaves like the OpenAI API.&lt;/p&gt;

&lt;p&gt;To your infrastructure, it's an orchestration layer capable of routing requests to hundreds of proprietary and open-weight models.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;Because now your code isn't coupled to Anthropic.&lt;/p&gt;

&lt;p&gt;Or Google.&lt;/p&gt;

&lt;p&gt;Or OpenAI.&lt;/p&gt;

&lt;p&gt;It's coupled to one API contract.&lt;/p&gt;

&lt;p&gt;Everything else becomes configuration.&lt;/p&gt;

&lt;p&gt;And in software engineering, configuration almost always ages better than code.&lt;/p&gt;

&lt;p&gt;That was the first thing that stood out to me.&lt;/p&gt;

&lt;p&gt;OpenRouter isn't really selling access to models.&lt;/p&gt;

&lt;p&gt;It's selling abstraction.&lt;/p&gt;

&lt;p&gt;And good abstractions are usually what make systems maintainable in the long run.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you found this helpful, leave a comment and follow me so you don't miss Part 2 of the series, coming soon.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>javascript</category>
      <category>llm</category>
    </item>
    <item>
      <title># Side projects don't fail because of bad code. They fail because...</title>
      <dc:creator>Franklyn Nmesoma</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:15:00 +0000</pubDate>
      <link>https://dev.to/franklyn_nmesoma/-side-projects-dont-fail-because-of-bad-code-they-fail-because-1hh5</link>
      <guid>https://dev.to/franklyn_nmesoma/-side-projects-dont-fail-because-of-bad-code-they-fail-because-1hh5</guid>
      <description>&lt;p&gt;It's crazy how nobody really talks about this.&lt;/p&gt;

&lt;p&gt;An idea pops into your head. You validate it. Maybe a few people tell you it's a good idea. Next thing you know, you're three weeks deep into building the next X (formerly Twitter).&lt;/p&gt;

&lt;p&gt;There's just one small problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're not building for users. You're building for yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The way developers see products is completely different from the way users see them.&lt;/p&gt;

&lt;p&gt;A developer sees pixels, color gradients, load times, request speeds, database queries, security, and architecture.&lt;/p&gt;

&lt;p&gt;The user sees one thing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Most users don't care that your font size is off by 2px. They don't care whether you're using React, Vue, Laravel, Next.js, PostgreSQL, MongoDB, or whatever new framework launched last week.&lt;/p&gt;

&lt;p&gt;What they care about is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I use this thing without getting frustrated?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the real question.&lt;/p&gt;

&lt;p&gt;Think about the products you use every day. Why do they have millions of users?&lt;/p&gt;

&lt;p&gt;It isn't because the UI is beautiful.&lt;/p&gt;

&lt;p&gt;It isn't because the architecture is perfect.&lt;/p&gt;

&lt;p&gt;It's because they're usable.&lt;/p&gt;

&lt;p&gt;Can users understand your product without watching a tutorial?&lt;/p&gt;

&lt;p&gt;Can they complete important actions without getting confused?&lt;/p&gt;

&lt;p&gt;Can they find what they're looking for without clicking through five different screens?&lt;/p&gt;

&lt;p&gt;If the answer is no, then you don't have a technical problem.&lt;/p&gt;

&lt;p&gt;You have a product problem.&lt;/p&gt;

&lt;p&gt;And product problems kill side projects much faster than technical ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second reason: developers love over-complicating things.
&lt;/h2&gt;

&lt;p&gt;A lot of developers struggle with this, especially when building side projects.&lt;/p&gt;

&lt;p&gt;A simple note-taking application somehow becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-powered&lt;/li&gt;
&lt;li&gt;Real-time&lt;/li&gt;
&lt;li&gt;Multi-tenant&lt;/li&gt;
&lt;li&gt;Offline-first&lt;/li&gt;
&lt;li&gt;Blockchain-enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All before a single user has written their first note.&lt;/p&gt;

&lt;p&gt;A notes app doesn't need AI.&lt;/p&gt;

&lt;p&gt;It needs to let users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create notes&lt;/li&gt;
&lt;li&gt;Save notes&lt;/li&gt;
&lt;li&gt;View notes&lt;/li&gt;
&lt;li&gt;Delete notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;There's a difference between building the right thing and just building things.&lt;/p&gt;

&lt;p&gt;The hack?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;KISS.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Keep It Simple, Stupid.&lt;/p&gt;

&lt;p&gt;(Or Keep It Short and Simple if you're feeling polite.)&lt;/p&gt;

&lt;p&gt;The principle is the same.&lt;/p&gt;

&lt;p&gt;Your application should perform its primary task exceptionally well before you start adding features nobody asked for.&lt;/p&gt;

&lt;p&gt;The more complexity you introduce, the more opportunities you create for things to break.&lt;/p&gt;

&lt;p&gt;Build with KISS in mind and thank me later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The third reason nobody talks about: no deployment plan.
&lt;/h2&gt;

&lt;p&gt;This one hurts.&lt;/p&gt;

&lt;p&gt;You spend months building.&lt;/p&gt;

&lt;p&gt;Next.js for the frontend.&lt;/p&gt;

&lt;p&gt;Laravel for the backend.&lt;/p&gt;

&lt;p&gt;PostgreSQL for the database.&lt;/p&gt;

&lt;p&gt;Redis for caching.&lt;/p&gt;

&lt;p&gt;Docker because everyone on YouTube says you should learn Docker.&lt;/p&gt;

&lt;p&gt;Everything sounds cool until it's time to deploy.&lt;/p&gt;

&lt;p&gt;Now you're trying to figure out hosting, environment variables, SSL certificates, databases, storage, monitoring, backups, and why your frontend suddenly can't talk to your backend.&lt;/p&gt;

&lt;p&gt;This is where many side projects quietly die.&lt;/p&gt;

&lt;p&gt;Not because the code was bad.&lt;/p&gt;

&lt;p&gt;Because nobody thought about operations.&lt;/p&gt;

&lt;p&gt;Before writing your first line of code, ask yourself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How is this thing actually going to run?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How will the services communicate?&lt;/p&gt;

&lt;p&gt;How will updates be deployed?&lt;/p&gt;

&lt;p&gt;How will users access it?&lt;/p&gt;

&lt;p&gt;How will I keep it online when something breaks?&lt;/p&gt;

&lt;p&gt;Your goal isn't to build something that works on your machine.&lt;/p&gt;

&lt;p&gt;Your goal is to build something users can depend on.&lt;/p&gt;

&lt;p&gt;Those are two very different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Most side projects don't die because of bad code.&lt;/p&gt;

&lt;p&gt;They die because nobody wanted to use them.&lt;/p&gt;

&lt;p&gt;They die because they're overengineered.&lt;/p&gt;

&lt;p&gt;They die because the developer spent more time choosing technologies than understanding users.&lt;/p&gt;

&lt;p&gt;And sometimes they die because nobody thought about what happens after the code is finished.&lt;/p&gt;

&lt;p&gt;The irony is that writing the code is often the easiest part.&lt;/p&gt;

&lt;p&gt;Building something people actually use?&lt;/p&gt;

&lt;p&gt;That's the hard part.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sideprojects</category>
      <category>developers</category>
      <category>programming</category>
    </item>
    <item>
      <title>What actually happens between you pressing **Pay** and the money moving?</title>
      <dc:creator>Franklyn Nmesoma</dc:creator>
      <pubDate>Wed, 17 Jun 2026 06:15:00 +0000</pubDate>
      <link>https://dev.to/franklyn_nmesoma/what-actually-happens-between-you-pressing-pay-and-the-money-moving-5fma</link>
      <guid>https://dev.to/franklyn_nmesoma/what-actually-happens-between-you-pressing-pay-and-the-money-moving-5fma</guid>
      <description>&lt;p&gt;You buy something online. You enter your card details, tap &lt;strong&gt;PAY&lt;/strong&gt;, and within seconds you see:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Payment Successful.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simple enough, right?&lt;/p&gt;

&lt;p&gt;However, here's the interesting part:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The money hasn't actually reached the business owner yet.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I know. Sounds strange.&lt;/p&gt;

&lt;p&gt;After all, if your account has already been debited and the website says payment was successful, shouldn't the merchant have the money immediately?&lt;/p&gt;

&lt;p&gt;Not exactly.&lt;/p&gt;

&lt;p&gt;To understand what really happens, let's introduce the key characters involved in this transaction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You&lt;/strong&gt; – the customer making the payment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The vendor&lt;/strong&gt; – the business selling the product or service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The payment processor&lt;/strong&gt; – Paystack, Stripe, Flutterwave, Remita, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your bank&lt;/strong&gt; – the institution holding your money.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The merchant's bank&lt;/strong&gt; – where the business eventually receives its funds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's follow the journey of your money.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;## What happens after you click Pay?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The process begins almost immediately after you hit that button.&lt;/p&gt;

&lt;p&gt;First, the payment processor receives your payment request. Think of it as the middleman coordinating the entire process.&lt;/p&gt;

&lt;p&gt;The processor then contacts your bank and essentially asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"This customer is trying to spend ₦10,000. Do they have enough money, and should this transaction be approved?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your bank checks a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the card valid?&lt;/li&gt;
&lt;li&gt;Is there enough money in the account?&lt;/li&gt;
&lt;li&gt;Has the card been blocked?&lt;/li&gt;
&lt;li&gt;Does anything about this transaction look suspicious?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on these checks, your bank sends back one of two responses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Approved&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Declined&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the payment is declined, the transaction stops there.&lt;/p&gt;

&lt;p&gt;If it's approved, the payment processor immediately notifies the business that the payment was successful.&lt;/p&gt;

&lt;p&gt;This is usually when you receive that reassuring message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Payment Successful.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But remember:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;The merchant still hasn't received the money.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So where is the money?
&lt;/h2&gt;

&lt;p&gt;This is where many people get confused.&lt;/p&gt;

&lt;p&gt;That &lt;em&gt;"Payment Successful"&lt;/em&gt; message doesn't mean your money has been instantly teleported from your account into the merchant's account.&lt;/p&gt;

&lt;p&gt;What has happened is that the transaction has been &lt;em&gt;&lt;strong&gt;authorized&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The actual transfer of funds happens later through a process known as &lt;em&gt;&lt;strong&gt;settlement&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Settlement is simply the process of moving the approved funds to the merchant's bank account.&lt;/p&gt;

&lt;p&gt;Depending on the payment processor, settlement can happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Later that same day,&lt;/li&gt;
&lt;li&gt;The next business day,&lt;/li&gt;
&lt;li&gt;Or according to a predefined settlement schedule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means there is often a time gap between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;"The customer has paid."&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;_&lt;strong&gt;"The business has received the money."&lt;/strong&gt;&lt;br&gt;
_&lt;/p&gt;
&lt;h2&gt;
  
  
  But how does the business know the payment worked?
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine ordering food online.&lt;/p&gt;

&lt;p&gt;You've paid.&lt;/p&gt;

&lt;p&gt;The restaurant needs to know whether to start preparing your order.&lt;/p&gt;

&lt;p&gt;This is where something called a &lt;em&gt;&lt;strong&gt;webhook&lt;/strong&gt;&lt;/em&gt; comes in.&lt;/p&gt;

&lt;p&gt;Now, don't let the technical name scare you.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;webhook&lt;/em&gt; is simply an automated message sent from the payment processor to the business saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Hey, that payment went through. You can go ahead with the order."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without this notification system, businesses would have to manually check every single payment before processing orders.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Webhooks&lt;/em&gt; make the entire experience feel instant, even though multiple systems are communicating behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does all of this matter?
&lt;/h2&gt;

&lt;p&gt;Because most of us interact with payment systems every single day without ever thinking about what happens in the background.&lt;/p&gt;

&lt;p&gt;We pay for groceries.&lt;/p&gt;

&lt;p&gt;We buy movie tickets.&lt;/p&gt;

&lt;p&gt;We renew subscriptions.&lt;/p&gt;

&lt;p&gt;We transfer money.&lt;/p&gt;

&lt;p&gt;All in a matter of seconds.&lt;/p&gt;

&lt;p&gt;But behind that tiny &lt;strong&gt;Pay&lt;/strong&gt; button is an entire network of banks, payment processors, security checks, notifications, and settlement systems working together to make the experience seamless.&lt;/p&gt;

&lt;p&gt;The next time you see:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Payment Successful&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;you'll know that it's not the end of the journey.&lt;/p&gt;

&lt;p&gt;It's simply the moment everyone involved agrees:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;"Yes, this payment is valid. Let's continue moving the money where it needs to go."&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And somewhere in the background, a very busy orchestra of systems is making sure that happens without you ever noticing.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>stripe</category>
      <category>techtalks</category>
      <category>programming</category>
    </item>
    <item>
      <title>React isn't the problem. How we teach it is.</title>
      <dc:creator>Franklyn Nmesoma</dc:creator>
      <pubDate>Mon, 15 Jun 2026 06:15:00 +0000</pubDate>
      <link>https://dev.to/franklyn_nmesoma/react-isnt-the-problem-how-we-teach-it-is-38m8</link>
      <guid>https://dev.to/franklyn_nmesoma/react-isnt-the-problem-how-we-teach-it-is-38m8</guid>
      <description>&lt;p&gt;Ask a junior developer to explain what happens after a submit button is clicked. Most can't give a clear answer. For those who can, you'll probably hear something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"An API call is made to the back-end server and a response is returned."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fair enough.&lt;/p&gt;

&lt;p&gt;But probe a little further. Ask how the browser packages that request. Ask what HTTP method is being used. Ask where authentication comes into play. Ask how the server processes the request before the data ends up in a database.&lt;/p&gt;

&lt;p&gt;That's usually where the silence begins.&lt;/p&gt;

&lt;p&gt;This isn't because junior developers are lazy or incapable. We are not producing bad developers. We are producing developers with missing context.&lt;/p&gt;

&lt;p&gt;Somewhere along the way, we've started teaching abstractions before foundations.&lt;/p&gt;

&lt;p&gt;Many boot-camps and online tutorials optimize for outcomes. The promise is simple: build a portfolio, get job-ready, land your first role. React fits perfectly into that narrative because the results are immediate. You can build something impressive very quickly.&lt;/p&gt;

&lt;p&gt;The problem is that many learners are introduced to frameworks before they understand the systems those frameworks abstract away.&lt;/p&gt;

&lt;p&gt;They learn React before HTTP.&lt;/p&gt;

&lt;p&gt;Components before servers.&lt;/p&gt;

&lt;p&gt;State management before databases.&lt;/p&gt;

&lt;p&gt;Authentication libraries before authentication itself.&lt;/p&gt;

&lt;p&gt;And while there's nothing inherently wrong with React, teaching it too early often creates developers who know &lt;strong&gt;what&lt;/strong&gt; to do, but not necessarily &lt;strong&gt;why&lt;/strong&gt; they're doing it.&lt;/p&gt;

&lt;p&gt;The consequences usually show up later. &lt;/p&gt;

&lt;p&gt;Many developers fall into what is commonly called "tutorial hell", following along with project videos, copying code line by line, and feeling productive until it's time to build something independently. Suddenly, the confidence disappears because understanding was mistaken for familiarity.&lt;/p&gt;

&lt;p&gt;The same concern exists with AI-assisted development.&lt;/p&gt;

&lt;p&gt;To be clear, I'm not against AI. I use it regularly. Tools like ChatGPT, Claude, and Codex can significantly improve productivity. The issue arises when they replace thinking instead of supporting it.&lt;/p&gt;

&lt;p&gt;Debugging used to force developers into uncomfortable situations. You had to read documentation, search for solutions, experiment, fail repeatedly, and eventually understand the root cause of a problem. That struggle wasn't wasted effort; it was training.&lt;/p&gt;

&lt;p&gt;If every obstacle is immediately outsourced to an AI assistant, we risk skipping the very experiences that develop engineering judgment.&lt;/p&gt;

&lt;p&gt;This is especially concerning because software development isn't just about producing working code. As developers grow, they are expected to make decisions, evaluate trade-offs, anticipate failure points, and understand the implications of the systems they build.&lt;/p&gt;

&lt;p&gt;That level of competence isn't developed through prompting alone.&lt;/p&gt;

&lt;p&gt;If I were designing a web development curriculum, this is the order I'd teach things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML/CSS&lt;/li&gt;
&lt;li&gt;JavaScript fundamentals&lt;/li&gt;
&lt;li&gt;Browser fundamentals&lt;/li&gt;
&lt;li&gt;HTTP and APIs&lt;/li&gt;
&lt;li&gt;Basic back-end concepts&lt;/li&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;Authentication and authorization&lt;/li&gt;
&lt;li&gt;Then React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the time students reach React, they wouldn't just know how to use &lt;code&gt;useEffect&lt;/code&gt;; they would understand why data fetching exists in the first place. They wouldn't just know how to submit forms; they would understand what happens after the submit button is clicked.&lt;/p&gt;

&lt;p&gt;React isn't the problem.&lt;/p&gt;

&lt;p&gt;AI isn't the problem.&lt;/p&gt;

&lt;p&gt;The problem is that we're moving people through the foundations too quickly and expecting the gaps to fill themselves over time.&lt;/p&gt;

&lt;p&gt;Sometimes they do.&lt;/p&gt;

&lt;p&gt;Often, they don't.&lt;/p&gt;

&lt;p&gt;So I'll end with this question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are we gatekeeping, or are we teaching the next generation of developers to build without truly understanding what they're building?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>softwareengineering</category>
      <category>react</category>
      <category>developers</category>
    </item>
  </channel>
</rss>
