<?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: Sameer Saleem</title>
    <description>The latest articles on DEV Community by Sameer Saleem (@sameer_saleem).</description>
    <link>https://dev.to/sameer_saleem</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%2F3507512%2Fcf9fbf19-f5b7-43fb-ab6a-bb0d606f8457.jpg</url>
      <title>DEV Community: Sameer Saleem</title>
      <link>https://dev.to/sameer_saleem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sameer_saleem"/>
    <language>en</language>
    <item>
      <title>The Practical Guide to Claude Code: Build Scalable Apps Faster Without the Frustration</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Sat, 19 Sep 2026 12:23:49 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-practical-guide-to-claude-code-build-scalable-apps-faster-without-the-frustration-3pgp</link>
      <guid>https://dev.to/sameer_saleem/the-practical-guide-to-claude-code-build-scalable-apps-faster-without-the-frustration-3pgp</guid>
      <description>&lt;p&gt;If you’ve tried using terminal AI coding agents like &lt;strong&gt;Claude Code&lt;/strong&gt;, you’ve probably experienced one of two outcomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Magic Moment:&lt;/strong&gt; You ask it to fix a multi-file bug, and it inspects the files, runs the tests, and solves the problem in two minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Frustration:&lt;/strong&gt; It edits 15 files unexpectedly, breaks your build, and burns through your tokens without completing the task.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The difference between these two outcomes rarely comes down to the model itself. It comes down to &lt;strong&gt;how you set up your project and guide the tool&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Claude Code is not an autocomplete extension—it is an autonomous agent living in your shell. In this guide, we’ll skip the hype and break down practical, straightforward techniques to make your development workflow faster, cleaner, and more scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Grounding the Agent: The &lt;code&gt;CLAUDE.md&lt;/code&gt; File
&lt;/h2&gt;

&lt;p&gt;When a new human developer joins your team, you don't expect them to guess your code formatting, naming conventions, or folder structures. You onboard them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt; is the onboarding document for your AI agent. Placed at the root of your project, this file is automatically read every time you start a session.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to include in &lt;code&gt;CLAUDE.md&lt;/code&gt;:
&lt;/h3&gt;

&lt;p&gt;Keep it short, clear, and direct. Avoid fluffy language.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Guidelines&lt;/span&gt;

&lt;span class="gu"&gt;## Commands&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Dev Server: &lt;span class="sb"&gt;`npm run dev`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Build: &lt;span class="sb"&gt;`npm run build`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Run Tests: &lt;span class="sb"&gt;`npm run test`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Single Test: &lt;span class="sb"&gt;`npx vitest run path/to/file.test.ts`&lt;/span&gt;

&lt;span class="gu"&gt;## Code Standards&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Framework: Next.js (App Router), TypeScript, Tailwind CSS
&lt;span class="p"&gt;-&lt;/span&gt; State Management: Zustand for global client state
&lt;span class="p"&gt;-&lt;/span&gt; Data Validation: Always use Zod schemas for API routes and form inputs

&lt;span class="gu"&gt;## Guidelines&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Never edit files inside &lt;span class="sb"&gt;`src/legacy/`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Keep components small and modular (under 150 lines).
&lt;span class="p"&gt;-&lt;/span&gt; Always write a corresponding unit test in &lt;span class="sb"&gt;`tests/`&lt;/span&gt; when adding a new utility.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By providing these clear instructions, you prevent the agent from introducing unexpected patterns or breaking established rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Master the Core Command Workflow
&lt;/h2&gt;

&lt;p&gt;Rather than sending unstructured, open-ended prompts, use built-in slash commands to structure your interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Plan First, Code Second" Approach
&lt;/h3&gt;

&lt;p&gt;When tackling a large feature, &lt;strong&gt;never&lt;/strong&gt; start by telling the agent to "build X." Instead, separate planning from execution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generate a Plan:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plan Add a Stripe subscription checkout flow &lt;span class="k"&gt;for &lt;/span&gt;our SaaS tier.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent will inspect your existing codebase and outline the proposed changes across files without modifying any code yet.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Review and Adjust:&lt;/strong&gt;
Read the proposed plan. If something looks off, give feedback: &lt;em&gt;"Do not create a new API route; use our existing server action pattern."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute:&lt;/strong&gt;
Once the plan is approved, instruct the agent to proceed with execution.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Managing Session Context
&lt;/h3&gt;

&lt;p&gt;AI models degrade in performance when their context window becomes cluttered with old logs, stale error traces, and discarded code attempts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;/compact&lt;/code&gt; to summarize the current session history and reclaim memory without losing progress.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;/clear&lt;/code&gt; to start a completely fresh session when switching to an unrelated task.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;/rewind&lt;/code&gt; if the agent takes a wrong turn, safely restoring your code and conversation to an earlier checkpoint.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Building Scalable Apps: The "Component-First" Strategy
&lt;/h2&gt;

&lt;p&gt;Asking an AI agent to build an entire page at once often leads to overly complex, unmaintainable code. To keep your application scalable, break your requests into small, testable boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Task Execution
&lt;/h3&gt;

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

&lt;blockquote&gt;
&lt;p&gt;❌ &lt;em&gt;"Build the entire user settings dashboard with password reset, avatar upload, and email preferences."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Break the task into clear steps:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;✅ &lt;em&gt;"Create a reusable Zod schema and TypeScript type for the user settings form in &lt;code&gt;src/lib/validations/user.ts&lt;/code&gt;."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;em&gt;"Build the &lt;code&gt;AvatarUpload&lt;/code&gt; component in &lt;code&gt;src/components/settings/AvatarUpload.tsx&lt;/code&gt;."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;em&gt;"Implement the form layout and connect the validation schema."&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;This approach ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every piece of code remains modular and easier to review.&lt;/li&gt;
&lt;li&gt;You can test each sub-component individually.&lt;/li&gt;
&lt;li&gt;If a step fails, troubleshooting is straightforward.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Let the Agent Run Tests and Fix Its Own Errors
&lt;/h2&gt;

&lt;p&gt;One of the strongest advantages of a terminal agent is its ability to interact with your local environment.&lt;/p&gt;

&lt;p&gt;Instead of manually checking if the generated code works, let the agent verify its own work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Example prompt&lt;/span&gt;
claude &lt;span class="s2"&gt;"Implement the discount code calculation in src/lib/cart.ts, then run 'npm run test' to verify your changes pass."&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a test fails, the agent reads the error output, identifies the issue, adjusts the code, and re-runs the test until it passes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Agent Reads Test Output] -&amp;gt; ❌ 1 Test Failed (Invalid Discount Math)
[Agent Edits Code]       -&amp;gt; Corrected rounding logic in cart.ts
[Agent Re-runs Test]     -&amp;gt; ✅ All 12 Tests Passed

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Summary Checklist for Maximum Productivity
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Project Setup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create a &lt;code&gt;CLAUDE.md&lt;/code&gt; in the repository root.&lt;/td&gt;
&lt;td&gt;Prevents repetitive instructions and keeps code style consistent.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Feature Work&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always run &lt;code&gt;/plan&lt;/code&gt; before writing code for complex tasks.&lt;/td&gt;
&lt;td&gt;Catch architectural flaws before files are modified.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;/compact&lt;/code&gt; or &lt;code&gt;/clear&lt;/code&gt; between distinct tasks.&lt;/td&gt;
&lt;td&gt;Keeps responses fast, accurate, and lower cost.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Task Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Request small, incremental edits rather than massive rewrites.&lt;/td&gt;
&lt;td&gt;Improves code quality and simplifies review.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Verification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instruct the agent to run tests or linters automatically.&lt;/td&gt;
&lt;td&gt;Catch bugs before committing code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Using an AI coding agent effectively isn't about letting it write your entire application unsupervised. It's about taking on the role of a &lt;strong&gt;tech lead&lt;/strong&gt;: establishing clear constraints, reviewing proposed plans, and letting the agent handle implementation and testing details.&lt;/p&gt;

&lt;p&gt;By incorporating &lt;code&gt;CLAUDE.md&lt;/code&gt; guidelines, planning before executing, and working incrementally, you can speed up your development workflow while building clean, scalable applications.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What strategies do you use when working with terminal AI agents?&lt;/strong&gt; Do you prefer keeping them on a tight leash with manual approvals, or giving them autonomy to run tests and fix errors? Share your thoughts below! 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Vector Databases: Types, Architecture, and Why They Power Modern Apps</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Wed, 12 Aug 2026 08:25:54 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/vector-databases-types-architecture-and-why-they-power-modern-apps-35m7</link>
      <guid>https://dev.to/sameer_saleem/vector-databases-types-architecture-and-why-they-power-modern-apps-35m7</guid>
      <description>&lt;p&gt;If you built an AI app in the early days of LLMs, you probably hit a wall pretty quickly: &lt;strong&gt;Large Language Models have no long-term memory.&lt;/strong&gt; They forget who your user is, they don't know your company's proprietary documentation, and pasting 500-page PDFs directly into prompt context windows is expensive, slow, and prone to context rot.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Vector Databases&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Whether you're building a Retrieval-Augmented Generation (RAG) pipeline, an autonomous AI agent with long-term memory, or a high-performance recommendation engine, vector databases have become core infrastructure.&lt;/p&gt;

&lt;p&gt;Here is the complete guide to how vector databases work, the main types available, and why they matter for modern application development.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. What is a Vector Database?
&lt;/h3&gt;

&lt;p&gt;Traditional databases (like PostgreSQL, MySQL, or MongoDB) store scalar data—strings, integers, JSON objects—and rely on &lt;strong&gt;exact matches&lt;/strong&gt; or range queries. If you search for &lt;code&gt;"laptop"&lt;/code&gt;, a traditional full-text index looks for the exact characters &lt;code&gt;l-a-p-t-o-p&lt;/code&gt;. If your document contains &lt;code&gt;"MacBook"&lt;/code&gt; or &lt;code&gt;"portable computer"&lt;/code&gt;, keyword search misses it completely unless manually tagged.&lt;/p&gt;

&lt;p&gt;Vector databases, on the other hand, store &lt;strong&gt;high-dimensional vector embeddings&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"MacBook Air"&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="err"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-0.198&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.812&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"Portable Computer"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-0.201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.799&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"Juicy Apple"&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="err"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.884&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-0.012&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An embedding model (like OpenAI's &lt;code&gt;text-embedding-3&lt;/code&gt;, Cohere, or an open-source model like &lt;code&gt;bge-large-en&lt;/code&gt;) transforms unstructured data—text, images, audio, or video—into a sequence of floating-point numbers.&lt;/p&gt;

&lt;p&gt;In this high-dimensional space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concepts with &lt;strong&gt;similar meanings&lt;/strong&gt; are placed geometrically close to each other.&lt;/li&gt;
&lt;li&gt;Unrelated concepts sit far apart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A vector database indexes these numerical arrays so you can run &lt;strong&gt;Nearest Neighbor (k-NN)&lt;/strong&gt; queries to find semantically similar items in milliseconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+--------------------------------------------------------------------------+
|                            THE VECTOR FLOW                               |
|                                                                          |
|  Unstructured Data   ===&amp;gt;   Embedding Model   ===&amp;gt;   High-Dim Vector     |
|  ("User Query")             (e.g., OpenAI)           [0.12, -0.45, ...]   |
|                                                               |          |
|                                                               v          |
|  Top K Results       &amp;lt;===   Vector DB Index   &amp;lt;===   Distance Search     |
|  (Nearest Neighbors)        (HNSW / IVF)             (Cosine/Dot Prod)   |
+--------------------------------------------------------------------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. How Similarity Search Works
&lt;/h3&gt;

&lt;p&gt;Because calculating exact distances across billions of high-dimensional vectors is computationally impossible in real-time, vector databases use &lt;strong&gt;Approximate Nearest Neighbor (ANN)&lt;/strong&gt; indexing algorithms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HNSW (Hierarchical Navigable Small World):&lt;/strong&gt; A multi-layer graph structure where top layers act as fast express lanes and lower layers pinpoint exact neighbors. It offers maximum accuracy and speed at the cost of higher RAM usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IVF (Inverted File Index):&lt;/strong&gt; Groups vectors into Voronoi clusters. During queries, the database searches only within the nearest cluster centroids, drastically speeding up queries over massive datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PQ (Product Quantization):&lt;/strong&gt; Compresses vectors into smaller byte representations to save memory while preserving approximate distance metrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Distance Metrics
&lt;/h4&gt;

&lt;p&gt;When querying vectors, the database calculates geometric distance using one of three metrics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Cosine Similarity : Measures the ANGLE between vectors (best for normalized text).
2. Dot Product       : Measures ANGLE + MAGNITUDE (fastest for pre-normalized vectors).
3. Euclidean (L2)    : Measures STRAIGHT-LINE DISTANCE between vector endpoints.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. The Types of Vector Databases
&lt;/h3&gt;

&lt;p&gt;Not all vector databases are built the same. The ecosystem has divided into distinct categories based on operational needs and scale:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Popular Examples&lt;/th&gt;
&lt;th&gt;Best Used For&lt;/th&gt;
&lt;th&gt;Trade-offs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dedicated Vector DBs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pinecone, Qdrant, Milvus, Weaviate&lt;/td&gt;
&lt;td&gt;Massive scale (10M+ to Billions of vectors), low-latency requirements&lt;/td&gt;
&lt;td&gt;Extra infrastructure component to manage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relational / SQL Extensions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PostgreSQL + &lt;code&gt;pgvector&lt;/code&gt; / &lt;code&gt;pgvectorscale&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Teams already using SQL; moderate scale (&amp;lt;10M vectors)&lt;/td&gt;
&lt;td&gt;Shares CPU/RAM resources with primary database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Search Engine Extensions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Elasticsearch, OpenSearch&lt;/td&gt;
&lt;td&gt;Hybrid keyword + vector search; heavy enterprise logs&lt;/td&gt;
&lt;td&gt;Higher memory footprint and query overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Embedded / In-Process&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chroma, LanceDB, FAISS&lt;/td&gt;
&lt;td&gt;Local development, edge computing, mobile, zero-copy processing&lt;/td&gt;
&lt;td&gt;Limited multi-node horizontal scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  4. Deep Dive into the Categories
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A. Dedicated Vector Databases (Pinecone, Qdrant, Milvus)
&lt;/h4&gt;

&lt;p&gt;Built ground-up specifically for high-dimensional arrays.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qdrant (Rust-based):&lt;/strong&gt; Renowned for fast payload filtering, payload indexing, and memory efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pinecone (Managed Serverless):&lt;/strong&gt; Offers zero-ops infrastructure with dynamic scaling and pay-per-query pricing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Milvus (Distributed):&lt;/strong&gt; Built for billion-scale enterprise deployments requiring GPU-accelerated indexing and cloud-native architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  B. Relational Extensions (&lt;code&gt;pgvector&lt;/code&gt; on Postgres)
&lt;/h4&gt;

&lt;p&gt;The most popular architectural movement is bringing vectors directly into relational data. With extensions like &lt;code&gt;pgvector&lt;/code&gt; or &lt;code&gt;pgvectorscale&lt;/code&gt;, you store embeddings inside a standard SQL column.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Creating a table with a 1536-dimensional vector column&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;knowledge_base&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="n"&gt;JSONB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Creating an HNSW index for ultra-fast similarity search&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;knowledge_base&lt;/span&gt; 
&lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;hnsw&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;vector_cosine_ops&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Performing a combined SQL + Vector query&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;knowledge_base&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'category'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'engineering'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'[0.012, -0.421, ...]'&lt;/span&gt; &lt;span class="c1"&gt;-- '&amp;lt;=&amp;gt;' is Cosine Distance&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why developers love &lt;code&gt;pgvector&lt;/code&gt;:&lt;/strong&gt; You perform joins, ACID transactions, metadata filters, and vector searches in a single SQL query without running a separate database service.&lt;/p&gt;

&lt;h4&gt;
  
  
  C. Embedded Vector Databases (LanceDB, Chroma)
&lt;/h4&gt;

&lt;p&gt;Embedded databases run inside your application process (like SQLite). &lt;strong&gt;LanceDB&lt;/strong&gt;, built on top of the Apache Arrow columnar format, allows zero-copy retrieval directly from disk or S3 buckets without loading everything into expensive RAM.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Why Vector Databases Are Essential in Application Development
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Powering Production RAG (Retrieval-Augmented Generation)
&lt;/h4&gt;

&lt;p&gt;LLMs hallucinate when asked about private enterprise data. RAG solves this by fetching real-time context before passing the query to the model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pinecone&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pinecone&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAIEmbeddings&lt;/span&gt;

&lt;span class="n"&gt;pc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pinecone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PINECONE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enterprise-kb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-embedding-3-small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Convert user query to vector
&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is our company policy on remote work setup budgets?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;query_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embed_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Retrieve top 3 semantically related internal documents
&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&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;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include_metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Feed retrieved content into LLM context window
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matches&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Autonomous Agent Memory
&lt;/h4&gt;

&lt;p&gt;Autonomous agents need short-term (scratchpad) and long-term (episodic) memory. By storing user interactions and agent execution steps in a vector store, agents recall past decisions and preferences seamlessly across long chat histories.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Hybrid Search (Dense + Sparse)
&lt;/h4&gt;

&lt;p&gt;Pure vector search sometimes fails on exact code names, part numbers, or specific legal terms (e.g., looking for &lt;code&gt;"Error 504"&lt;/code&gt; vs &lt;code&gt;"Gateway Timeout"&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Modern vector databases handle &lt;strong&gt;Hybrid Search&lt;/strong&gt;—combining BM25 keyword scoring with dense vector similarity—to ensure exact name hits are never missed while keeping semantic context intact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Final Score = (α * Sparse_BM25_Score) + ((1 - α) * Dense_Vector_Score)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  6. Architectural Decision Framework
&lt;/h3&gt;

&lt;p&gt;When choosing your vector storage strategy, follow this quick playbook:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Starting a new project / &amp;lt; 5 Million vectors:&lt;/strong&gt; Use &lt;strong&gt;PostgreSQL with `pgvector&lt;/strong&gt;`. Keeping vectors alongside your existing database saves hours of synchronization overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building a client-side app / Local CLI tool:&lt;/strong&gt; Use &lt;strong&gt;LanceDB&lt;/strong&gt; or &lt;strong&gt;Chroma&lt;/strong&gt; in-process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale exceeds 10M+ vectors / Latency &amp;lt; 20ms required:&lt;/strong&gt; Migrate to a dedicated vector database like &lt;strong&gt;Qdrant&lt;/strong&gt; (for open-source/self-hosted control) or &lt;strong&gt;Pinecone&lt;/strong&gt; (for serverless cloud simplicity).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Already deeply invested in Elastic / OpenSearch:&lt;/strong&gt; Enable their built-in k-NN vector indexes to avoid spinning up new vendors.&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>vectordatabase</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>database</category>
    </item>
    <item>
      <title>The Cookie That Wouldn't Die (and How We Fixed It)</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Sat, 04 Jul 2026 13:01:08 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-cookie-that-wouldnt-die-and-how-we-fixed-it-38lm</link>
      <guid>https://dev.to/sameer_saleem/the-cookie-that-wouldnt-die-and-how-we-fixed-it-38lm</guid>
      <description>&lt;p&gt;You know that feeling when everything works perfectly in development, but production decides to play games?&lt;/p&gt;

&lt;p&gt;I spent yesterday chasing down a ghost. Our authentication flow was flawless locally—users could log in and out without a hitch. But the moment we deployed to production, logout mysteriously stopped working. Cookies refused to clear. Users were stuck in an endless login loop.&lt;/p&gt;

&lt;p&gt;After hours of staring at logs and questioning my life choices, the culprit turned out to be something deceptively simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;cookieStore.delete()&lt;/code&gt; wasn't enough.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In development, with &lt;code&gt;secure: false&lt;/code&gt;, cookies are forgiving. They'll let you delete them without matching every attribute. But in production, with &lt;code&gt;secure: true&lt;/code&gt; and &lt;code&gt;sameSite: "lax"&lt;/code&gt;, the browser demands perfection. If your delete operation doesn't specify the exact same cookie attributes, it simply... ignores you.&lt;/p&gt;

&lt;p&gt;The fix was surprisingly elegant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// What didn't work:&lt;/span&gt;
&lt;span class="nx"&gt;cookieStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;COOKIE_NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// What worked:&lt;/span&gt;
&lt;span class="nx"&gt;cookieStore&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="nx"&gt;COOKIE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&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;span class="nx"&gt;COOKIE_OPTIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;// Expire immediately&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting an empty cookie with &lt;code&gt;maxAge: 0&lt;/code&gt; and the exact same attributes as the original forces the browser to respect the expiration. No ambiguity, no edge cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🍪 Production cookies are strict. Match attributes exactly when clearing.&lt;/li&gt;
&lt;li&gt;🔍 &lt;code&gt;delete()&lt;/code&gt; isn't always reliable in Next.js—&lt;code&gt;set()&lt;/code&gt; with &lt;code&gt;maxAge: 0&lt;/code&gt; is your friend.&lt;/li&gt;
&lt;li&gt;💡 The subtle differences between dev and prod environments will humble you every time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shoutout to everyone who's debugged authentication issues past midnight. You're not alone. ❤️&lt;/p&gt;

&lt;h1&gt;
  
  
  NextJS #WebDevelopment #Authentication #Debugging #JavaScript #ProdIssues #DevLife
&lt;/h1&gt;

</description>
      <category>nextjs</category>
      <category>backend</category>
      <category>cookie</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Google Cloud NEXT '26: The Dawn of the Agentic Era</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Mon, 27 Apr 2026 09:41:16 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/google-cloud-next-26-the-dawn-of-the-agentic-era-1kc6</link>
      <guid>https://dev.to/sameer_saleem/google-cloud-next-26-the-dawn-of-the-agentic-era-1kc6</guid>
      <description>&lt;p&gt;Google Cloud NEXT '26 just concluded in Las Vegas (April 22–24), and the shift is undeniable: we have moved from the era of "Chatting with AI" to the era of &lt;strong&gt;Agentic AI&lt;/strong&gt;. Google’s focus this year wasn't just on faster models, but on a vertically integrated stack—chips, data, and platforms—designed to let AI agents reason, plan, and execute complex business workflows autonomously.&lt;/p&gt;

&lt;p&gt;Here is the ultimate breakdown of the major announcements that will define the cloud landscape for the next year.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Hardware: The 8th Gen TPU Revolution
&lt;/h3&gt;

&lt;p&gt;To power thousands of autonomous agents, Google unveiled its most specialized silicon yet. For the first time, the eighth-generation Tensor Processing Units (TPUs) are split into two distinct architectures.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TPU 8t (Training):&lt;/strong&gt; Optimized for the massive throughput required to train frontier models in weeks rather than months.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TPU 8i (Inference):&lt;/strong&gt; Purpose-built for serving models with near-zero latency. Google claims an &lt;strong&gt;80% improvement in performance per dollar&lt;/strong&gt; for inference tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NVIDIA Partnership:&lt;/strong&gt; Google announced it will be among the first hyperscalers to offer the new &lt;strong&gt;NVIDIA Vera Rubin NVL72&lt;/strong&gt; systems, integrated directly into their AI Hypercomputer architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The Gemini Enterprise Agent Platform
&lt;/h3&gt;

&lt;p&gt;This was the "star of the show." Google is no longer just providing APIs; they are providing a complete workspace to build and manage AI workforces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 3.1 Pro &amp;amp; Flash:&lt;/strong&gt; The latest models are now generally available, featuring enhanced reasoning for multi-step tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Studio:&lt;/strong&gt; A low-code interface that allows developers (and even business users) to build, test, and govern agents using natural language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Inbox:&lt;/strong&gt; A centralized management hub where humans can monitor exactly what their AI agents are doing, approve sensitive actions, and step in when needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. The "Agentic Data Cloud"
&lt;/h3&gt;

&lt;p&gt;An agent is only as good as the data it can access. Google introduced the &lt;strong&gt;Agentic Data Cloud&lt;/strong&gt; to solve the "data bottleneck" for AI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge Catalog:&lt;/strong&gt; A universal context engine that autonomously maps your entire business data estate. It uses Gemini to "tag" and connect data points so agents understand your company's specific lingo and internal logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Cloud Lakehouse:&lt;/strong&gt; Standardized on &lt;strong&gt;Apache Iceberg&lt;/strong&gt;, this allows agents to query data across AWS, Azure, and Google Cloud with zero-copy federation. You can leave your data where it is and still use Google's AI to reason over it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed Lustre:&lt;/strong&gt; A storage breakthrough delivering &lt;strong&gt;10 terabytes per second&lt;/strong&gt; of throughput, ensuring that your GPUs and TPUs are never "starved" for data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Security: Agentic Defense
&lt;/h3&gt;

&lt;p&gt;As agents become more powerful, security must become proactive. Google introduced several "Agentic SecOps" tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dark Web Intelligence Agent:&lt;/strong&gt; Uses Gemini to build a nuanced security profile of your organization based on real-time dark web activity, filtering out noise with &lt;strong&gt;98% accuracy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Threat Hunting Agent:&lt;/strong&gt; Proactively searches for novel attack patterns that traditional signature-based systems might miss.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 What This Means for Developers
&lt;/h3&gt;

&lt;p&gt;In 2026, your job is shifting from &lt;strong&gt;writing code&lt;/strong&gt; to &lt;strong&gt;orchestrating intent&lt;/strong&gt;. With the new &lt;strong&gt;Google Cloud Data Agent Kit&lt;/strong&gt;, you can now use your IDE (like VS Code) as a native workspace where agents autonomously handle the "grunt work" of data science, testing, and deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "1-Click" Future:&lt;/strong&gt; Between the eighth-gen TPUs and the new &lt;strong&gt;Agentic Taskforce&lt;/strong&gt; features in Workspace, the goal is clear: Google wants to reduce the "Time to Outcome" for every business process from hours to seconds.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=X-MDFb3GRys" rel="noopener noreferrer"&gt;Google Cloud Next '26 Highlights&lt;/a&gt;&lt;br&gt;&lt;br&gt;
This video provides a comprehensive wrap-up of the event, including the new TPU architectures and India's emerging role in the global AI hub strategy.&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>gcpnext</category>
      <category>gemini</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Ultimate Generative AI Roadmap (2026 Edition)</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Mon, 27 Apr 2026 09:38:12 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-ultimate-generative-ai-roadmap-2026-edition-17gl</link>
      <guid>https://dev.to/sameer_saleem/the-ultimate-generative-ai-roadmap-2026-edition-17gl</guid>
      <description>&lt;p&gt;In 2026, the barrier between "using AI" and "building AI" has vanished. The "Prompt Engineer" role has been absorbed into the &lt;strong&gt;AI Systems Architect&lt;/strong&gt;. To stay relevant this year, you don't just need to know how to call an API—you need to understand the underlying infrastructure of &lt;strong&gt;Compound AI Systems&lt;/strong&gt;, &lt;strong&gt;Agentic RAG&lt;/strong&gt;, and &lt;strong&gt;World Models&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This roadmap is designed to take you from a standard developer to a 2026-ready AI Engineer in 6-9 months.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 1: Foundations &amp;amp; Python Mastery (Month 1)
&lt;/h3&gt;

&lt;p&gt;Python remains the undisputed language of AI. Before touching an LLM, you must master the data-handling ecosystem.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core Skills:&lt;/strong&gt; Advanced Python (Async/Await, Type Hinting), NumPy, and Pandas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Math for AI:&lt;/strong&gt; Linear algebra (for embeddings), calculus (for backpropagation), and probability (for understanding model temperature and top-p).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Learning 101:&lt;/strong&gt; Understanding neural networks, loss functions, and gradients.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 2: The Transformer &amp;amp; LLM Fundamentals (Month 2)
&lt;/h3&gt;

&lt;p&gt;You cannot build robust systems if you treat the model as a black box. You need to understand the &lt;strong&gt;Attention Mechanism&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concepts:&lt;/strong&gt; Tokenization, Context Windows, and the difference between Encoder-only (BERT), Decoder-only (GPT), and Encoder-Decoder (T5) architectures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hands-on:&lt;/strong&gt; Build a "Mini-GPT" from scratch using PyTorch to understand how tokens are predicted.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 3: Prompting to Programming (Month 3)
&lt;/h3&gt;

&lt;p&gt;In 2026, we've moved from "Magic Phrases" to &lt;strong&gt;Structured Output&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Techniques:&lt;/strong&gt; Chain of Thought (CoT), Few-Shot Prompting, and ReAct (Reason + Act).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools:&lt;/strong&gt; Master &lt;strong&gt;Pydantic&lt;/strong&gt; for enforcing JSON schemas. Your code should never "hope" for a valid response; it should "enforce" it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projects:&lt;/strong&gt; Build a text-to-structured-data engine that converts messy emails into typed JSON objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 4: Agentic RAG &amp;amp; Vector Databases (Month 4-5)
&lt;/h3&gt;

&lt;p&gt;Standard RAG (Retrieval-Augmented Generation) is now considered "legacy." In 2026, we use &lt;strong&gt;Agentic RAG&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval:&lt;/strong&gt; Move beyond simple vector search. Learn &lt;strong&gt;Hybrid Search&lt;/strong&gt; (Vector + BM25) and &lt;strong&gt;Graph-Enhanced RAG&lt;/strong&gt; (Knowledge Graphs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration:&lt;/strong&gt; Master &lt;strong&gt;LangGraph&lt;/strong&gt; or &lt;strong&gt;PydanticAI&lt;/strong&gt; to build stateful agents that can loop, self-correct, and use tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector Infrastructure:&lt;/strong&gt; Use &lt;strong&gt;pgvector&lt;/strong&gt; (PostgreSQL) or &lt;strong&gt;Pinecone Serverless&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 5: Fine-Tuning &amp;amp; Small Language Models (Month 6)
&lt;/h3&gt;

&lt;p&gt;Why use a $30/mo model when a $0.05 local model can do the same task? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SLMs:&lt;/strong&gt; Work with &lt;strong&gt;Llama 4 (8B)&lt;/strong&gt; or &lt;strong&gt;Phi-4&lt;/strong&gt;. Learn how to run them locally using &lt;strong&gt;Ollama&lt;/strong&gt; or &lt;strong&gt;vLLM&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Techniques:&lt;/strong&gt; &lt;strong&gt;PEFT&lt;/strong&gt; (Parameter-Efficient Fine-Tuning) and &lt;strong&gt;LoRA&lt;/strong&gt;. Learn to fine-tune a model to follow your specific company's brand voice or code style.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 6: AI-Native DevOps &amp;amp; MLOps (Month 7-9)
&lt;/h3&gt;

&lt;p&gt;The final step is moving from "it works on my machine" to "it works for 10,000 users."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Containerization with &lt;strong&gt;Docker&lt;/strong&gt; and scaling with &lt;strong&gt;Kubernetes&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring:&lt;/strong&gt; Implement &lt;strong&gt;Observability&lt;/strong&gt; (LangSmith, Helicone) to track latency, token costs, and "Hallucination Rates."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation:&lt;/strong&gt; Build an &lt;code&gt;evals/&lt;/code&gt; suite using &lt;strong&gt;LLM-as-a-Judge&lt;/strong&gt; to automatically test every change you make to your prompt or model.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 The 2026 "Secret Sauce": Continual Learning
&lt;/h3&gt;

&lt;p&gt;The best AI Engineers this year aren't just building static apps; they are building &lt;strong&gt;Continual Learning Systems&lt;/strong&gt;. These are apps that get smarter with every user interaction by saving "Corrected Responses" into a feedback loop for future fine-tuning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Goal for 2026:&lt;/strong&gt; Stop building chatbots. Start building &lt;strong&gt;Autonomous Systems&lt;/strong&gt; that solve problems while you sleep.&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>ai</category>
      <category>rag</category>
      <category>roadmap2026</category>
    </item>
    <item>
      <title>Claude Code vs. Cursor vs. Aider: The 2026 Battle for Your Terminal and IDE</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Wed, 25 Mar 2026 11:31:41 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/claude-code-vs-cursor-vs-aider-the-2026-battle-for-your-terminal-and-ide-3cb4</link>
      <guid>https://dev.to/sameer_saleem/claude-code-vs-cursor-vs-aider-the-2026-battle-for-your-terminal-and-ide-3cb4</guid>
      <description>&lt;p&gt;By March 2026, the question is no longer "Should I use AI to code?" but "Which AI agent should own my workflow?" The landscape has split into three distinct powerhouses: &lt;strong&gt;Cursor&lt;/strong&gt; (the integrated experience), &lt;strong&gt;Aider&lt;/strong&gt; (the precise pair programmer), and the newcomer that changed everything, &lt;strong&gt;Claude Code&lt;/strong&gt; (the terminal-native agent).&lt;/p&gt;

&lt;p&gt;If you’re wondering which tool should be your "Daily Driver" in 2026, this guide breaks down the strengths, the "Computer Use" capabilities, and the exact scenarios where each shines.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Contenders: High-Level Overview
&lt;/h3&gt;

&lt;p&gt;In 2026, we categorize these tools by how much "agency" they have over your file system and environment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Aider&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interface&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full IDE (VS Code Fork)&lt;/td&gt;
&lt;td&gt;Terminal CLI&lt;/td&gt;
&lt;td&gt;Terminal Agent + Shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agentic Level&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (Composer Mode)&lt;/td&gt;
&lt;td&gt;Medium (Chat-to-Edit)&lt;/td&gt;
&lt;td&gt;Extreme (Autonomous Shell)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Feature Building&lt;/td&gt;
&lt;td&gt;Refactoring / Git Sync&lt;/td&gt;
&lt;td&gt;Debugging &amp;amp; Infra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native (Built-in)&lt;/td&gt;
&lt;td&gt;Plugin-based&lt;/td&gt;
&lt;td&gt;Deep Integration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  2. Cursor: The "Vibe Coding" King
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt; remains the gold standard for developers who want a seamless, visual experience. In 2026, its &lt;strong&gt;Composer&lt;/strong&gt; mode has evolved into a "Project Architect" that can scaffold entire full-stack features while you watch the UI update in real-time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The 2026 Edge:&lt;/strong&gt; Cursor’s "Shadow Workspace" indexing. It pre-computes your entire codebase's logic so it can predict your next move before you finish the prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use it:&lt;/strong&gt; When you are building &lt;strong&gt;new UI features&lt;/strong&gt; or working on complex layouts where you need to see the code and the file tree simultaneously.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Downside:&lt;/strong&gt; It can be "too heavy" for quick terminal tasks or server-side debugging.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Aider: The Git-Centric Surgeon
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Aider&lt;/strong&gt; has carved out a massive following among senior devs who value precision and "Code DNA" preservation. It is a terminal-based tool that excels at editing existing files and automatically committing changes with perfect commit messages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The 2026 Edge:&lt;/strong&gt; &lt;strong&gt;Architect Mode.&lt;/strong&gt; Aider now uses a two-step process: high-level reasoning first, followed by a surgical "coding" model to apply the diffs. It is legendary for its low hallucination rate in complex refactors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use it:&lt;/strong&gt; For &lt;strong&gt;refactoring large logic blocks&lt;/strong&gt; or working within a strict Git workflow where you want every AI change to be a discrete, well-documented commit.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Claude Code: The Terminal-Native Agent
&lt;/h3&gt;

&lt;p&gt;The newest titan in the ring, &lt;strong&gt;Claude Code&lt;/strong&gt;, isn't just a code editor—it’s a &lt;strong&gt;Shell Agent&lt;/strong&gt;. It doesn't just write code; it runs your tests, fixes the &lt;code&gt;404&lt;/code&gt; error it finds in your logs, and uses "Computer Use" to verify the fix in a headless browser.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The 2026 Edge:&lt;/strong&gt; &lt;strong&gt;Autonomous Debugging.&lt;/strong&gt; Claude Code can say, &lt;em&gt;"I noticed the build failed; I'm going to read the error log, check the documentation for that library via the web, and apply a patch."&lt;/em&gt; It is the only tool that feels like a true Junior Engineer sitting at your desk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to use it:&lt;/strong&gt; For &lt;strong&gt;complex debugging, environment setup, and infra-work&lt;/strong&gt;. If you have a bug that spans five files and a database config, Claude Code is the one to call.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. The 2026 Decision Matrix: Which one when?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Case A: "I need to build a new Dashboard page with 3 charts."
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Winner: Cursor.&lt;/strong&gt; Use the visual interface to drag and drop components and let the AI handle the Tailwind/React boilerplate.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case B: "I have a legacy bug in my Auth middleware that I can't find."
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Winner: Claude Code.&lt;/strong&gt; Give it the command &lt;code&gt;claude "find why the JWT is expiring early and fix it"&lt;/code&gt;. It will run the server, trace the logs, and find the culprit autonomously.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case C: "I need to migrate my entire DB schema from Prisma to Drizzle."
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Winner: Aider.&lt;/strong&gt; Its ability to handle massive search-and-replace refactors with surgical precision makes it the safest bet for high-stakes migrations.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚀 The "Secret Sauce": CLAUDE.md and .cursorrules
&lt;/h3&gt;

&lt;p&gt;In 2026, the real pros are using &lt;strong&gt;Hybrid Workflows&lt;/strong&gt;. They use &lt;strong&gt;Cursor&lt;/strong&gt; for the UI and keep a &lt;strong&gt;Claude Code&lt;/strong&gt; session open in the integrated terminal for the "heavy lifting" like running migrations or writing E2E tests.&lt;/p&gt;

&lt;p&gt;Regardless of your choice, ensure you have a &lt;code&gt;CLAUDE.md&lt;/code&gt; or &lt;code&gt;.cursorrules&lt;/code&gt; file in your root directory. This acts as the "Memory" for these agents, telling them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"We use Functional Components only."&lt;/li&gt;
&lt;li&gt;"Always use Zod for validation."&lt;/li&gt;
&lt;li&gt;"Never use &lt;code&gt;localStorage&lt;/code&gt;; use &lt;code&gt;cookies&lt;/code&gt;."&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>webdev</category>
      <category>claudecode</category>
      <category>cursor</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What was your win this week?</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Tue, 10 Mar 2026 07:17:18 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/what-was-your-win-this-week-3181</link>
      <guid>https://dev.to/sameer_saleem/what-was-your-win-this-week-3181</guid>
      <description></description>
      <category>weeklyretro</category>
      <category>tfhdailystandup</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Ultimate Guide to GraphQL + Apollo Server (2026 Edition)</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Tue, 10 Mar 2026 05:59:10 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-ultimate-guide-to-graphql-apollo-server-2026-edition-6d0</link>
      <guid>https://dev.to/sameer_saleem/the-ultimate-guide-to-graphql-apollo-server-2026-edition-6d0</guid>
      <description>&lt;p&gt;In 2026, the debate between REST and GraphQL has settled into a powerful synergy. &lt;strong&gt;Apollo Server 4&lt;/strong&gt; (and its latest minor updates) has moved toward a "GraphOS-native" approach, focusing on extreme performance, native TypeScript ESM support, and a streamlined middleware system.&lt;/p&gt;

&lt;p&gt;If you're building a data-rich application in 2026, you don't just want an API; you want a self-documenting, type-safe &lt;strong&gt;Supergraph&lt;/strong&gt;. Here is how to build it from scratch.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Architecture: Schema-First in 2026
&lt;/h3&gt;

&lt;p&gt;Modern Apollo development emphasizes a &lt;strong&gt;Schema-First&lt;/strong&gt; workflow. You define the "shape" of your data in GraphQL SDL (Schema Definition Language), and Apollo ensures your resolvers match that shape perfectly.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Project Initialization (ESM &amp;amp; TS)
&lt;/h3&gt;

&lt;p&gt;In 2026, Node.js strictly follows ECMAScript Modules (ESM). We'll set up a project that leverages top-level &lt;code&gt;await&lt;/code&gt; and native TypeScript execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;apollo-server-2026
&lt;span class="nb"&gt;cd &lt;/span&gt;apollo-server-2026
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm pkg &lt;span class="nb"&gt;set type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @apollo/server graphql
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; typescript tsx @types/node
npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Defining the Schema
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;src/schema.ts&lt;/code&gt;. In 2026, we lean heavily into &lt;strong&gt;Custom Scalars&lt;/strong&gt; and &lt;strong&gt;Namespacing&lt;/strong&gt; to keep large graphs maintainable.&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`#graphql
  type User {
    id: ID!
    username: String!
    email: String!
    posts: [Post!]!
  }

  type Post {
    id: ID!
    title: "String!"
    content: String
    author: User!
  }

  type Query {
    users: [User!]!
    user(id: ID!): User
    posts: [Post!]!
  }

  type Mutation {
    createPost(title: "String!, content: String, authorId: ID!): Post!"
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Crafting High-Performance Resolvers
&lt;/h3&gt;

&lt;p&gt;Resolvers in 2026 are all about avoiding the &lt;strong&gt;N+1 problem&lt;/strong&gt;. We use &lt;code&gt;context&lt;/code&gt; to inject data sources or loaders.&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;// src/resolvers.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;span class="na"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// 2026 Best Practice: Use a DataLoader here to batch requests&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByAuthorId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;span class="na"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;createPost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dataSources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&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="nx"&gt;args&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;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Launching the Standalone Server
&lt;/h3&gt;

&lt;p&gt;Apollo Server 4's &lt;code&gt;startStandaloneServer&lt;/code&gt; is the fastest way to get a production-ready endpoint with built-in CORS and body parsing.&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;// src/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;startStandaloneServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@apollo/server/standalone&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;typeDefs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./schema.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./resolvers.js&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;server&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;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;typeDefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// The 'context' function runs for every request&lt;/span&gt;
&lt;span class="kd"&gt;const&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;startStandaloneServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Inject your DB client (Prisma/Drizzle) here&lt;/span&gt;
    &lt;span class="na"&gt;dataSources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myDatabaseClient&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;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`🚀  Server ready at: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Integrating with Next.js (App Router)
&lt;/h3&gt;

&lt;p&gt;If you're using Next.js 15+, you'll use the &lt;code&gt;@apollo/experimental-nextjs-app-support&lt;/code&gt; library to bridge the gap between Server Components and your GraphQL API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/ApolloClient.ts (2026 Setup)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpLink&lt;/span&gt; &lt;span class="p"&gt;}&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;@apollo/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerApolloClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InMemoryCache&lt;/span&gt; &lt;span class="p"&gt;}&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;@apollo/experimental-nextjs-app-support&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;registerApolloClient&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpLink&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;uri&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://localhost:4000&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;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🚀 What’s New in Apollo (2026 Docs)?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Apollo MCP (Model Context Protocol):&lt;/strong&gt; 2026 introduces native support for AI agents. You can now expose your GraphQL schema as "Tools" for LLMs to query directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative Cache IDs:&lt;/strong&gt; You no longer need to manually write &lt;code&gt;merge&lt;/code&gt; functions for complex types; Apollo 4.x now handles object identity through &lt;code&gt;@id&lt;/code&gt; directives in the schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Config Persisted Queries:&lt;/strong&gt; To prevent "Query Injection" attacks, Apollo now supports automatic persisted queries (APQ) out of the box, reducing bandwidth and increasing security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native &lt;code&gt;@defer&lt;/code&gt; support:&lt;/strong&gt; You can now stream slow-loading parts of your query (like a user's post history) while the main user profile renders instantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro-Tip:&lt;/strong&gt; Use &lt;strong&gt;Apollo Studio Explorer&lt;/strong&gt; (accessible via your server URL) to test your queries. In 2026, it includes AI-powered "Query Suggestions" that write your fragments for you based on your component needs.&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>graphql</category>
      <category>apollo</category>
      <category>backend</category>
    </item>
    <item>
      <title>The Ultimate Guide to Stripe + Next.js (2026 Edition)</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Tue, 24 Feb 2026 07:36:28 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-ultimate-guide-to-stripe-nextjs-2026-edition-2f33</link>
      <guid>https://dev.to/sameer_saleem/the-ultimate-guide-to-stripe-nextjs-2026-edition-2f33</guid>
      <description>&lt;p&gt;In 2026, the "best way" to handle payments in Next.js has shifted. With the maturity of &lt;strong&gt;Server Actions&lt;/strong&gt;, &lt;strong&gt;Embedded Checkout&lt;/strong&gt;, and the &lt;strong&gt;React 19&lt;/strong&gt; integration in Next.js 15+, the friction of building a secure, high-conversion payment flow is at an all-time low.&lt;/p&gt;

&lt;p&gt;This guide skips the legacy API routes and focuses on the high-performance, &lt;strong&gt;Server-Action-first&lt;/strong&gt; architecture recommended for 2026.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The 2026 Lifecycle: Embedded vs. Hosted
&lt;/h3&gt;

&lt;p&gt;Stripe now strongly pushes &lt;strong&gt;Embedded Checkout&lt;/strong&gt;. Unlike the old redirect, it uses an &lt;code&gt;iframe&lt;/code&gt; or a web component that lives &lt;em&gt;inside&lt;/em&gt; your Next.js page, keeping your user on your domain while offloading all PCI compliance to Stripe.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Modern Project Setup
&lt;/h3&gt;

&lt;p&gt;We’ll initialize a Next.js project with the App Router and the latest Stripe SDKs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest my-store-2026 &lt;span class="nt"&gt;--typescript&lt;/span&gt; &lt;span class="nt"&gt;--tailwind&lt;/span&gt; &lt;span class="nt"&gt;--app&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my-store-2026
npm &lt;span class="nb"&gt;install &lt;/span&gt;stripe @stripe/stripe-js @stripe/react-stripe-js

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Secure Environment Variables
&lt;/h3&gt;

&lt;p&gt;Never expose your &lt;code&gt;STRIPE_SECRET_KEY&lt;/code&gt;. In 2026, Next.js environment variables are strictly enforced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .env.local
STRIPE_SECRET_KEY="sk_test_51..."
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_51..."
STRIPE_WEBHOOK_SECRET="whsec_..."

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. The Server Action Pattern
&lt;/h3&gt;

&lt;p&gt;In the 2026 docs, &lt;strong&gt;Server Actions&lt;/strong&gt; are the standard for creating Checkout Sessions. This eliminates the need for &lt;code&gt;/api/checkout&lt;/code&gt; folders.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/app/actions/stripe.ts&lt;/code&gt;:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="p"&gt;}&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;@/lib/stripe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&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;next/headers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&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;createCheckoutSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;priceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;origin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;origin&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;session&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;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessions&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;ui_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;embedded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// This enables the 2026 Embedded UI&lt;/span&gt;
    &lt;span class="na"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;priceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subscription&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;return_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/return?session_id={CHECKOUT_SESSION_ID}`&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_secret&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;h3&gt;
  
  
  5. Implementing Embedded Checkout
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;EmbeddedCheckout&lt;/code&gt; component from &lt;code&gt;@stripe/react-stripe-js&lt;/code&gt; provides a seamless "no-redirect" experience.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/components/CheckoutForm.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadStripe&lt;/span&gt; &lt;span class="p"&gt;}&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;@stripe/stripe-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EmbeddedCheckoutProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EmbeddedCheckout&lt;/span&gt; &lt;span class="p"&gt;}&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;@stripe/react-stripe-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCheckoutSession&lt;/span&gt; &lt;span class="p"&gt;}&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;@/app/actions/stripe&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;stripePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadStripe&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;NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CheckoutForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;priceId&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;priceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We fetch the clientSecret via the Server Action&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchClientSecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;clientSecret&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createCheckoutSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;priceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;clientSecret&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkout"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EmbeddedCheckoutProvider&lt;/span&gt; &lt;span class="na"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stripePromise&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchClientSecret&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;EmbeddedCheckout&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;EmbeddedCheckoutProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h3&gt;
  
  
  6. Critical: The 2026 Webhook Handler
&lt;/h3&gt;

&lt;p&gt;Even with Server Actions, &lt;strong&gt;Route Handlers&lt;/strong&gt; are still required for Webhooks because Stripe needs a static URL to "ping" when a payment succeeds.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/app/api/webhook/route.ts&lt;/code&gt;:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt; &lt;span class="p"&gt;}&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;@/lib/stripe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&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;next/headers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&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;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;body&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stripe-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;webhooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constructEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;signature&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;STRIPE_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="o"&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Webhook Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle the event&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;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkout.session.completed&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;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// 2026 Practice: Trigger a background sync or email service&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`💰 Payment confirmed for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&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;h3&gt;
  
  
  🚀 What's New in the 2026 Stripe Docs?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Link Authentication Element:&lt;/strong&gt; Automatically detects if a user has a "Link" account (Stripe's 1-click checkout) and pre-fills their details, increasing conversion by up to 10%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptive Pricing:&lt;/strong&gt; Now natively supported in Checkout Sessions—Stripe automatically shows the price in the user's local currency based on their IP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Tax ID Collection:&lt;/strong&gt; You can now toggle &lt;code&gt;tax_id_collection: { enabled: true }&lt;/code&gt; directly in the session creation to handle global B2B tax compliance without extra logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro-Tip:&lt;/strong&gt; For local testing, use the &lt;strong&gt;Stripe CLI&lt;/strong&gt;. Run &lt;code&gt;stripe listen --forward-to localhost:3000/api/webhook&lt;/code&gt; to simulate successful payments on your local machine.&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>stripe</category>
      <category>typescript</category>
    </item>
    <item>
      <title>The Ultimate Guide to OAuth with Express.js (2025 Edition)</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Fri, 23 Jan 2026 10:45:20 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-ultimate-guide-to-oauth-with-expressjs-2025-edition-5137</link>
      <guid>https://dev.to/sameer_saleem/the-ultimate-guide-to-oauth-with-expressjs-2025-edition-5137</guid>
      <description>&lt;p&gt;To build a secure, industry-standard authentication system in 2026, you must use the &lt;strong&gt;Backend for Frontend (BFF) pattern&lt;/strong&gt;. This approach ensures that sensitive tokens (Access/Refresh tokens) are never exposed to the browser's JavaScript, mitigating XSS risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Principles
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use OpenID Connect (OIDC):&lt;/strong&gt; Prefer &lt;code&gt;openid-client&lt;/code&gt; over Passport.js for better OIDC compliance and PKCE support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PKCE (Proof Key for Code Exchange):&lt;/strong&gt; Always use PKCE, even for confidential server-side clients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Sessions:&lt;/strong&gt; Use server-side sessions (e.g., Redis) and encrypted &lt;code&gt;HttpOnly&lt;/code&gt; cookies.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Codebase
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dependencies:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;npm install express express-session openid-client dotenv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation (&lt;code&gt;app.js&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express-session&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;generators&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openid-client&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Secure Session Configuration&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;session&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;__Host-auth-session&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;secret&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;SESSION_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;resave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;saveUninitialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;secure&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sameSite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lax&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="c1"&gt;// 24 hours&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 2. OIDC Client Discovery &amp;amp; Setup&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;initializeOidc&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;issuer&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;Issuer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;discover&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;OIDC_ISSUER&lt;/span&gt;&lt;span class="p"&gt;);&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="nx"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;client_id&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;CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;client_secret&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;CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redirect_uris&lt;/span&gt;&lt;span class="p"&gt;:&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;REDIRECT_URI&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;response_types&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="s1"&gt;code&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;span class="c1"&gt;// 3. Login Route (Initiate PKCE)&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;code_verifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;codeVerifier&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;code_challenge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;codeChallenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code_verifier&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code_verifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;code_verifier&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;authUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorizationUrl&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;openid email profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;code_challenge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;code_challenge_method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;S256&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Callback Route (Exchange Code for Tokens)&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/callback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callbackParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;tokenSet&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="nf"&gt;callback&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;REDIRECT_URI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;code_verifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code_verifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Store tokens in session, NOT in browser storage&lt;/span&gt;
    &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokenSet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tokenSet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OAuth Callback Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authentication failed&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;span class="c1"&gt;// 5. Protected Route Example&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Welcome, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;initializeOidc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BFF Server running on http://localhost:3000&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;h3&gt;
  
  
  Environment Variables (&lt;code&gt;.env&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OIDC_ISSUER=https://your-provider.com
CLIENT_ID=your_client_id
CLIENT_SECRET=your_client_secret
REDIRECT_URI=http://localhost:3000/callback
SESSION_SECRET=a_very_long_random_string_here

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Summary of Security Measures
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Authorization Code Flow + PKCE:&lt;/strong&gt; Prevents authorization code injection and interception.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Tokens in Frontend:&lt;/strong&gt; The frontend only sees a session cookie; the Express server handles the raw Access/Refresh tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Discovery:&lt;/strong&gt; Using &lt;code&gt;Issuer.discover&lt;/code&gt; ensures your app stays compatible with provider updates (key rotation, endpoint changes).&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>oauth</category>
      <category>express</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Beyond the Syntax: The Anatomy of a High-Impact Developer’s Daily Routine</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Mon, 19 Jan 2026 11:14:09 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/beyond-the-syntax-the-anatomy-of-a-high-impact-developers-daily-routine-1bk5</link>
      <guid>https://dev.to/sameer_saleem/beyond-the-syntax-the-anatomy-of-a-high-impact-developers-daily-routine-1bk5</guid>
      <description>&lt;p&gt;There is a common myth that a developer’s day is 8 hours of frantic typing against a black-and-green terminal. Whether you are a Junior pushing your first PR or a Senior Architect balancing three system designs, the reality is much more nuanced.&lt;/p&gt;

&lt;p&gt;The "Daily Life" of a successful developer isn't just about writing code; it’s about &lt;strong&gt;managing cognitive load, communication, and constant evolution.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The "Deep Work" Window (AM)
&lt;/h2&gt;

&lt;p&gt;Most high-impact developers protect their mornings. This is when your brain is freshest for complex logic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Junior Perspective:&lt;/strong&gt; This is your time to struggle productively. Try to solve the bug for 30 minutes before asking for help.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Senior Perspective:&lt;/strong&gt; This is when you tackle the "Gordian Knots" of the architecture or perform deep-dive code reviews that ensure the codebase stays maintainable.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Turn off Slack/Teams. The "context switching tax" can cost you up to 40% of your productive time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. The Art of the Stand-up (The Sync)
&lt;/h2&gt;

&lt;p&gt;The Daily Stand-up isn't a status report for a boss; it’s a strategy session for a team.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What to say:&lt;/strong&gt; "Yesterday I finished X. Today I’m working on Y. I’m blocked by Z."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Professional Edge:&lt;/strong&gt; Don’t just list tasks. Highlight &lt;strong&gt;risks&lt;/strong&gt;. If you think a feature will take longer than planned, the stand-up is the time to raise the flag, not the day of the deadline.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Communication is the Real "Hard Skill"
&lt;/h2&gt;

&lt;p&gt;As you progress from Junior to Senior, you’ll notice a shift: you spend less time talking to computers and more time talking to humans.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; If you solve a weird bug, write it down in the Wiki.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mentorship:&lt;/strong&gt; Seniors use their afternoons for 1:1s or pair programming, helping Juniors bypass the "invisible" hurdles of the environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. The "Maintenance" Phase (PM)
&lt;/h2&gt;

&lt;p&gt;Afternoons are often for the "shallow" but necessary tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answering emails and Slack messages.&lt;/li&gt;
&lt;li&gt;Updating Jira/Trello tickets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Learning:&lt;/strong&gt; The industry moves fast. Whether it's reading a technical blog, watching a tutorial, or experimenting with a new framework, professional developers bake "sharpening the saw" into their daily schedule.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Shutting Down (The Clean Exit)
&lt;/h2&gt;

&lt;p&gt;The best developers know how to leave work at work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The "Brain Dump":&lt;/strong&gt; Write down exactly where you left off. It makes starting tomorrow 10x easier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Physical Boundary:&lt;/strong&gt; Close the laptop. Close the IDE. Your brain needs the "cool down" period to prevent burnout.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Closing Thoughts
&lt;/h3&gt;

&lt;p&gt;Whether you are on Day 1 or Year 10, the goal is the same: &lt;strong&gt;Consistency over Intensity.&lt;/strong&gt; Coding is a marathon, not a sprint. The best daily routine is the one that allows you to be a great developer today and a healthy human tomorrow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does your "Deep Work" window look like? Let’s discuss in the comments!&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>career</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Ultimate Guide to Drizzle ORM + PostgreSQL (2025 Edition)</title>
      <dc:creator>Sameer Saleem</dc:creator>
      <pubDate>Tue, 13 Jan 2026 07:21:53 +0000</pubDate>
      <link>https://dev.to/sameer_saleem/the-ultimate-guide-to-drizzle-orm-postgresql-2025-edition-22b</link>
      <guid>https://dev.to/sameer_saleem/the-ultimate-guide-to-drizzle-orm-postgresql-2025-edition-22b</guid>
      <description>&lt;p&gt;While Prisma dominated the last few years, 2025 is the year of &lt;strong&gt;Drizzle ORM&lt;/strong&gt;. If you’re looking for a lightweight, "serverless-first" ORM that feels like writing raw SQL but provides world-class TypeScript autocompletion, this guide is for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Project Initialization
&lt;/h3&gt;

&lt;p&gt;We’ll set up a modern Node.js environment using TypeScript. Drizzle is designed to be extremely thin, making it perfect for Edge functions and standard Node backends alike.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;drizzle-postgres-2025
&lt;span class="nb"&gt;cd &lt;/span&gt;drizzle-postgres-2025
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;typescript tsx @types/node &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Install Drizzle and PostgreSQL Driver
&lt;/h3&gt;

&lt;p&gt;Drizzle doesn't use a heavy Rust engine. It’s just TypeScript. We’ll use the &lt;code&gt;postgres&lt;/code&gt; package (the fastest JS client) and &lt;code&gt;drizzle-kit&lt;/code&gt; for migrations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;drizzle-orm postgres
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; drizzle-kit

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Configure Your Connection
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file to hold your PostgreSQL connection string. Whether you’re using &lt;strong&gt;Neon&lt;/strong&gt;, &lt;strong&gt;Supabase&lt;/strong&gt;, or a local Docker instance, the format remains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL="postgresql://user:password@localhost:5432/my_db"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Define Your Schema in TypeScript
&lt;/h3&gt;

&lt;p&gt;Unlike Prisma, which uses a custom &lt;code&gt;.prisma&lt;/code&gt; language, Drizzle uses pure TypeScript. This means you can use functions and variables inside your schema definitions.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/db/schema.ts&lt;/code&gt;:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drizzle-orm/pg-core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;published&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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;h3&gt;
  
  
  5. Generate and Push Migrations
&lt;/h3&gt;

&lt;p&gt;Drizzle Kit reads your TypeScript schema and generates the SQL for you.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;drizzle.config.ts&lt;/code&gt; in your root:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drizzle-kit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/db/schema.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./drizzle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgresql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dbCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;url&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;DATABASE_URL&lt;/span&gt;&lt;span class="o"&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;Now, run the migration to sync your DB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx drizzle-kit push

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Instantiate the Client
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;src/db/index.ts&lt;/code&gt;. Drizzle is lightweight enough that you don't usually need a complex singleton pattern, but it's good practice for hot-reloading:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drizzle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;drizzle-orm/postgres-js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;postgres&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./schema&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;postgres&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;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Performing Type-Safe CRUD
&lt;/h3&gt;

&lt;p&gt;Drizzle gives you two ways to query: &lt;strong&gt;SQL-like&lt;/strong&gt; (for those who love SQL) and &lt;strong&gt;Relational Queries&lt;/strong&gt; (for those who love the Prisma API).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Prisma-like" way (Relational):&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create a user with a post&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUser&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dev Reader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello@dev.to&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="nf"&gt;returning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch users with their posts (The "Prisma" feel)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allUsers&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🚀 What Makes Drizzle the 2025 Choice?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero Code-Gen:&lt;/strong&gt; You don't need to run &lt;code&gt;npx generate&lt;/code&gt; every time you change a field. Your TypeScript types are always in sync with your schema automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "Edge" Advantage:&lt;/strong&gt; Because Drizzle has no heavy binary engine, it starts up in milliseconds on Vercel Functions or Cloudflare Workers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drizzle Studio:&lt;/strong&gt; Just like Prisma Studio, run &lt;code&gt;npx drizzle-kit studio&lt;/code&gt; to get a beautiful browser-based UI to explore your PostgreSQL data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL Power:&lt;/strong&gt; If you need to write a complex window function or a specific PostgreSQL extension query, Drizzle stays out of your way and lets you write SQL while still providing types for the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro-Tip:&lt;/strong&gt; If you are migrating from Prisma, check out the &lt;code&gt;drizzle-kit introspect&lt;/code&gt; command. It can look at your existing database and automatically generate the Drizzle TypeScript schema for you!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>drizzle</category>
      <category>postgres</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
