<?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</title>
    <description>The most recent home feed on DEV Community.</description>
    <link>https://dev.to</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed"/>
    <language>en</language>
    <item>
      <title>I built a radio station with one listener, and it runs in a terminal</title>
      <dc:creator>zhiyi guo</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:23:31 +0000</pubDate>
      <link>https://dev.to/fawinell/i-built-a-radio-station-with-one-listener-and-it-runs-in-a-terminal-4g7h</link>
      <guid>https://dev.to/fawinell/i-built-a-radio-station-with-one-listener-and-it-runs-in-a-terminal-4g7h</guid>
      <description>&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/DQ4YbSJF2XM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The film above is 86 seconds, and the middle of it is a real on-air moment. There is a longer unedited recording at the top of the &lt;a href="https://github.com/wine-fall/murmur" rel="noopener noreferrer"&gt;repo README&lt;/a&gt;. Watch either first, with the sound on. The rest of this post is why it exists and how it is put together.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;murmur runs in a terminal window and behaves like a radio station whose only listener is you. It picks a topic on its own and talks about it in a voice that sounds like a person. Then it plays a song, comes back, and keeps going. At the right hours it says good morning and good night. You do not have to answer any of it.&lt;/p&gt;

&lt;p&gt;When you do type something, the host replies in character. You chat for a bit. Then it eases back into the program.&lt;/p&gt;

&lt;p&gt;There is one host. A few questions on the first run write its character to a file. After that, nothing rewrites that file except you. What grows over time is a separate thing: what it knows about you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Every AI tool on my machine wants me to go faster. That is fine for work, and it is exhausting as company. I wanted something that sits closer to the person than to the task. A late-night radio host does that. They talk whether or not you are listening, they never ask you to respond, and when you do call in, they are glad and then they get back to the show.&lt;/p&gt;

&lt;p&gt;Nothing I found did the proactive half. Chat assistants wait for a prompt. Voice tools want to drive my editor. So the bet was simple: what if the AI speaks first and needs nothing back?&lt;/p&gt;

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

&lt;p&gt;It is TypeScript on Node 24, no build step, run straight from source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The brain is Claude&lt;/strong&gt;, opened through the Claude Agent SDK. It reuses your local Claude Code login, so there is no API key and no separate bill. It is a harnessed agent rather than a one-shot call. murmur gives it a small set of its own tools: search for a song, judge the candidates, commit a pick, update memory, run the setup guide. It is sealed off from your own Claude Code setup. None of your CLAUDE.md files, skills, MCP servers, or hooks reach it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The voice is fish-speech&lt;/strong&gt;, reached over a hosted HTTP endpoint you point it at. That is the reason it sounds like a person and not a screen reader. It is also the reason murmur is not a local tool, and I want to say that plainly: the brain and the voice are network services. What stays on your machine is the program logic, the keyboard, the mixer, the persona, and the memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Music comes through yt-dlp.&lt;/strong&gt; The rules it picks by live in a markdown file under &lt;code&gt;~/.murmur&lt;/code&gt;. The pick task re-reads that file before every song, so if you write "more Cantonese, no covers" while a track is playing, the change reaches the next pick or the one after.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mixer is a Web Audio graph&lt;/strong&gt; on &lt;code&gt;node-web-audio-api&lt;/code&gt;. Voice and music share one output stream. A gain envelope ducks the song under the host, so the lead-in is spoken over the head of the track and the back-announce over its tail. The song never stops for the voice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two processes.&lt;/strong&gt; The engine owns the program and the audio. The TUI is a separate process on OpenTUI under Bun, attached over a unix socket carrying newline-delimited JSON. Without Bun it falls back to a plain text host in the same process, and every command still works typed in full.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision people ask about
&lt;/h2&gt;

&lt;p&gt;The host's character does not evolve. I built the evolving version first. A background loop watched the conversation and rewrote the persona to fit the listener better. Within days it had drifted into the same generic assistant voice every chatbot has. Language-model rewrite loops mean-revert, and there was no checkpoint where a person could catch the drift.&lt;/p&gt;

&lt;p&gt;So the persona is frozen. It is a text file. You can open it and rewrite it whenever you like, and nothing changes it behind your back. The memory of you is a separate tier that does grow, with dates the code owns and citations back to the conversation that produced each fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is rough
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It needs a Claude Code subscription for the real brain. &lt;code&gt;--brain stub&lt;/code&gt; gives you a canned stand-in brain for a look around, and that is all it is.&lt;/li&gt;
&lt;li&gt;The voice is hosted. If you have no endpoint configured, it prints its lines instead of speaking. A local TTS is on the list, not in the code.&lt;/li&gt;
&lt;li&gt;Music picks sometimes stall or run long. There is an open issue with measurements.&lt;/li&gt;
&lt;li&gt;It is developed on macOS. Linux should be fine. Windows is untested.&lt;/li&gt;
&lt;li&gt;Onboarding is still being tuned by ear, and one path after &lt;code&gt;/quit&lt;/code&gt; misbehaves.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Node 24 or newer:&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; &lt;span class="nt"&gt;-g&lt;/span&gt; murmur-radio
murmur
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It launches even with pieces missing and offers to walk you through installing ffmpeg, yt-dlp, and a voice endpoint by talking to you. Say no once and it stops asking.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/wine-fall/murmur" rel="noopener noreferrer"&gt;https://github.com/wine-fall/murmur&lt;/a&gt; (MIT). Landing page: &lt;a href="https://wine-fall.github.io/murmur/" rel="noopener noreferrer"&gt;https://wine-fall.github.io/murmur/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you leave it on for an afternoon, I would like to know one thing: did it feel like radio, or like a chatbot with a timer?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>typescript</category>
      <category>cli</category>
      <category>showdev</category>
    </item>
    <item>
      <title>From SkillCheck to TraceMantle: Tracking Agent Skill Changes and Test Evidence</title>
      <dc:creator>Brad Kinnard</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:22:03 +0000</pubDate>
      <link>https://dev.to/moonrunnerkc/from-skillcheck-to-tracemantle-tracking-agent-skill-changes-and-test-evidence-3enh</link>
      <guid>https://dev.to/moonrunnerkc/from-skillcheck-to-tracemantle-tracking-agent-skill-changes-and-test-evidence-3enh</guid>
      <description>&lt;p&gt;I’ve renamed SkillCheck to TraceMantle and expanded its scope. The original project focused mainly on validating AI agent skill files. TraceMantle retains that functionality and adds support for tracking the files in a skill package, comparing changes, and checking whether previous test evidence still applies.&lt;/p&gt;

&lt;p&gt;The rename resolves a conflict with another project using the SkillCheck name. It also better reflects the tool’s broader purpose: helping developers assess both the contents of an agent skill and the evidence used to approve a particular version. The project is available on &lt;a href="https://github.com/moonrunnerkc/tracemantle" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I expanded the scope
&lt;/h2&gt;

&lt;p&gt;An agent skill can include more than its main &lt;code&gt;SKILL.md&lt;/code&gt; instruction file. Supporting scripts, reference documents, templates, and schemas can all affect how it behaves.&lt;/p&gt;

&lt;p&gt;Consider a skill that uses a Python helper to process a document. The instructions remain unchanged, but someone modifies the helper. A passing test report from the previous version may no longer cover the current behavior. Checking only the instruction file would miss an important part of that change.&lt;/p&gt;

&lt;p&gt;TraceMantle addresses this by connecting package changes with the evidence supplied for its checks. The aim is to make it easier to identify which earlier results remain relevant and which checks need to run again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;Skill validation remains part of the tool. TraceMantle checks frontmatter, file references, size limits, and compatibility advice. These checks help identify structural problems before a skill is committed or released.&lt;/p&gt;

&lt;p&gt;The expanded functionality adds three related capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bundle manifests:&lt;/strong&gt; A manifest records the files in a skill package and their content fingerprints. This allows TraceMantle to detect changes to supporting resources even when &lt;code&gt;SKILL.md&lt;/code&gt; stays the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence imports:&lt;/strong&gt; The tool can import results from a supported, version-pinned Promptfoo export format. It preserves the original export and records information about the evaluated inputs, configuration, checks, and execution context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence comparison:&lt;/strong&gt; A comparison checks supplied evidence against the package and a trusted policy. It reports changed inputs, incompatible results, and checks that require another run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The commands support text, JSON, and GitHub annotation output, allowing the same information to be used during local development or within a CI workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the approval rules work
&lt;/h2&gt;

&lt;p&gt;An imported report does not become trusted simply because it contains a passing result. The project owner or trusted automation must approve the evidence through a policy that identifies the required checks and their inputs.&lt;/p&gt;

&lt;p&gt;TraceMantle reads that policy from a specific trusted Git revision. Changes in the candidate package cannot replace the selected policy or quietly make a required check optional.&lt;/p&gt;

&lt;p&gt;The comparison also distinguishes a failed check from missing or unsuitable evidence. An &lt;code&gt;unknown&lt;/code&gt; result means the available evidence does not establish a pass. That distinction helps avoid treating an incomplete evaluation as either a successful release check or a confirmed failure of the skill itself.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/moonrunnerkc/tracemantle/blob/main/docs/evidence-workflow.md" rel="noopener noreferrer"&gt;evidence workflow documentation&lt;/a&gt; explains the supported format, approval process, and comparison states.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering changes behind the features
&lt;/h2&gt;

&lt;p&gt;The work also included improvements to parsing, configuration, reporting, and history storage. Analysis stages share a parsed document model to reduce repeated work, while file-size and parser limits help control resource use when processing external input.&lt;/p&gt;

&lt;p&gt;New history records are stored individually outside the evaluated bundle. Migration from the older history format is explicit and preserves the original files. The release workflow also checks built packages through clean installations, alongside tests, linting, and strict type checking.&lt;/p&gt;

&lt;p&gt;These changes support the broader workflow while keeping TraceMantle a local Python CLI and library.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool establishes
&lt;/h2&gt;

&lt;p&gt;TraceMantle analyzes files and supplied evidence. It does not run agent skills or evaluators itself, and a structurally valid skill is not proof that an agent will perform a task correctly.&lt;/p&gt;

&lt;p&gt;Its dependency analysis also has defined limits. It cannot infer every runtime dependency or arbitrary programming-language import. Trusted checks still need accurate input declarations, and incomplete coverage should require further evaluation.&lt;/p&gt;

&lt;p&gt;Live agent performance remains unverified in the project’s current evaluation record. Static checks, imported model judgments, and synthetic test fixtures have separate meanings and should remain distinguishable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status and migration
&lt;/h2&gt;

&lt;p&gt;TraceMantle 1.6.0 is published, with subsequent changes recorded under &lt;a href="https://github.com/moonrunnerkc/tracemantle/blob/main/CHANGELOG.md#unreleased" rel="noopener noreferrer"&gt;Unreleased&lt;/a&gt;. A recent audit identified two remaining defects involving Markdown dependency detection and numeric JSON input handling. One can cause a required rerun to be missed; the other can crash an import. Those corrections remain necessary before calling the implementation complete.&lt;/p&gt;

&lt;p&gt;Existing SkillCheck users should follow the &lt;a href="https://github.com/moonrunnerkc/tracemantle/blob/main/docs/migration.md" rel="noopener noreferrer"&gt;migration guide&lt;/a&gt;. TraceMantle is a separate Python distribution, so installing it is not an automatic upgrade of the old package.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/moonrunnerkc/tracemantle" rel="noopener noreferrer"&gt;repository&lt;/a&gt; contains the source, examples, tests, and implementation records for anyone interested in reviewing or contributing to the project.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
      <category>testing</category>
    </item>
    <item>
      <title>Day 8 - Relational Database 101 - PostgreSQL Internals</title>
      <dc:creator>Monirul Islam</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:20:00 +0000</pubDate>
      <link>https://dev.to/mislam-dev/day-8-relational-database-101-postgresql-internals-j9c</link>
      <guid>https://dev.to/mislam-dev/day-8-relational-database-101-postgresql-internals-j9c</guid>
      <description>&lt;p&gt;আপনি এবং আপনার friend একটা seminar-এ গেছেন, seminar-এ speaker-রা তাদের মতামত share করছেন। মাঝে মাঝে কিছু important কথা বলছেন। এই কথাগুলো আপনার friend note করছে, কিন্তু আপনি কিছুই note করেননি। Seminar শেষ হওয়ার পরের দিন আপনি সবকিছুই ভুলে গেছেন, আবছা আবছা মনে আছে কিন্তু সম্পূর্ণ মনে করতে পারছেন না। উপায় না পেয়ে আপনার friend-কে জিজ্ঞেস করলেন। ও সবকিছুই সুন্দর করে বলে দিলো। কারণটা নিশ্চয়ই বুঝতে পারছেন। ও কেন সবকিছু মনে রাখতে পারছে? কারণ ঐ friend সবকিছুই note করে রেখেছে বা save করে রেখেছে।&lt;/p&gt;

&lt;p&gt;একবার একটু technological দিকে আসি, আপনি যখন Facebook বা LinkedIn-এ কাউকে message করেন তখন সেটা সরাসরি তার কাছে send হয়। Reason হচ্ছে আপনারা connected। এখানে আপনি directly message তার কাছে send করছেন; network to network। কিন্তু মজার বিষয় হচ্ছে আপনি পরে যখন disconnected তখনও message-গুলো দেখতে পারছেন। হিসেব অনুযায়ী পরে message-গুলো থাকার কথা না। তাহলে হচ্ছেটা কী?&lt;/p&gt;

&lt;p&gt;আপনি বা অন্য কেউ যখন message send করছেন তখন সেই message-টা first-এ server-এ আসে, সেই server message-টা save করে। Save করার পর তারপর receiver-এর কাছে message-টা forward করে দেয়। সেই জন্য আপনি message-টা দেখতে পারছেন।&lt;/p&gt;

&lt;p&gt;এখন যেখানে বা যার মাধ্যমে save করা হচ্ছে, সেটাই হচ্ছে Database।&lt;/p&gt;




&lt;h2&gt;
  
  
  Database কী এবং কেন?
&lt;/h2&gt;

&lt;p&gt;সহজভাবে বললে database হচ্ছে data রাখার জায়গা। এখন বলতে পারেন file system-এর মাধ্যমে তো hard drive-এ data রাখা যেতেই পারে। তাহলে separate database-এর দরকার কী? এই question একদম valid। মজার ব্যাপার হচ্ছে database behind the scene-এ এই file system use করেই data store করে। এই শুনে আপনার মনে হতে পারে তাহলে direct file system use করলেই তো হয়।&lt;/p&gt;

&lt;p&gt;আসলে file system-এ data রাখাই যায়, কিন্তু problem হয় যখন search করা হয়। 1 million data থেকে একটা specific data খোঁজার জন্য file system প্রত্যেকটা file check করে তারপর আনতে হবে। তাহলে কতটা time লাগবে বুঝতে পারছেন? এত time লাগলে আপনার use কী থাকবে?&lt;/p&gt;

&lt;p&gt;এবার database কীভাবে কাজ করে এবং এই problem-টা solve করে সেটা জানার try করি। Database মূলত file system-এর ওপরে একটা layer তৈরি করে। এখানে শুধু file store করা ছাড়া আরও অনেকগুলো কাজ করা হয়ে থাকে। For example, database-এ indexing নামে একটা feature আছে। ওপরে যে 1 million data-এর ভেতরে searching করার যেই বিষয়টা বললাম, indexing করার পরে এই operation-এ time direct file system-এর থেকে 10x-20x কম লাগবে। কীভাবে লাগবে সেটা নিচে একটা section আছে ওখানে বুঝতে পারবেন।&lt;/p&gt;

&lt;p&gt;Hopefully database সম্পর্কে idea হয়ে গেছে।&lt;/p&gt;




&lt;h2&gt;
  
  
  Relational Database কী?
&lt;/h2&gt;

&lt;p&gt;একটা simple question করি? আপনার পিতা-মাতা ছাড়া logically আপনার কি কোনো অস্তিত্ব থাকবে? আপনার তো জন্মই হবে না। এর মানে আপনি তাদের ওপর dependable। তারা যদি history-তে exist না করে আপনিও করবেন না। এরকম অনেক রকম জিনিস আছে, আপনার ভাই বোন, দাদা দাদি।&lt;/p&gt;

&lt;p&gt;এখানে একটা জিনিস খেয়াল করেন, ২টা আলাদা type-এর জিনিসের মধ্যে একটা relation থাকছে। এখানে relation-গুলো কিন্তু একেকটা একেকরকম, কিন্তু কিছু limit বা কিছু জিনিস বাদ দিয়ে দিলে, কয়েকটা relationship থেকে যাবে।&lt;/p&gt;

&lt;p&gt;আসলে relational database-গুলো অনেকটা এভাবেই connected। এখানে প্রত্যেকটা entity-এর জন্য একটা করে table থাকে, table-এ column থাকে এবং row wise database add হয়। এই column-এই কিছু data রাখা হয় যাতে relation create করা যায়।&lt;br&gt;
For example, parent &amp;amp; children table আছে। এখন children table-এ row add করার সময়, একটা extra field add করবো, for example parent। এই parent-এর value দিয়ে determine হবে ঐ children-এর parent কে বা কারা।&lt;/p&gt;

&lt;p&gt;আসলে database একটা long long topic। এর syllabus অনেক long। অনেকটা সমুদ্রের মতন। আমি just একটা ধারণা দিয়েছি। নিচে অনেক অনেক topic নিয়ে আলোচনা করা হয়েছে। সেগুলো পড়লে অনেক কিছু শিখতে পারবেন hopefully।&lt;/p&gt;


&lt;h2&gt;
  
  
  ACID: Four Pillars of Database
&lt;/h2&gt;

&lt;p&gt;একটা জিনিস চিন্তা করেন, যখন কোনো কিছু standard হয়ে যায়, তখন তার required characteristics set করা হয়। যাতে same way-তে alternative নিয়ে আসা যায়। এরকমভাবে relational database-এর required characteristics হচ্ছে &lt;strong&gt;ACID&lt;/strong&gt;। ACID মূলত ৪টা word-এর সংক্ষিপ্ত form: Atomicity, Consistency, Isolation &amp;amp; Durability। একটা relational database-কে এই ৪টা জিনিস provide করতে হবে। নিচে এগুলো নিয়ে একটু আলোচনা করলে বুঝতে পারবেন।&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Atomicity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;একটা ছোট্ট গল্প বলি, তাহলে relate করতে easy হবে। ছোটবেলায় আমার আম্মা আমাকে টাকা দিয়ে দোকানে পাঠাতো এবং বলতো এই জিনিসটা নিয়ে আসবি আর বাকি টাকা দিয়ে cake কিনে খাবি। এটাও বলতো যদি ঐ জিনিস দোকানে না থাকে তাহলে পুরো টাকা ফেরত নিয়ে চলে আসবি, cake কিন্তু কিনবি না। এখন একটা জিনিস লক্ষ্য করুন। হয়তো ২টা কাজই হবে, না হলে একটাও হবে না।&lt;/p&gt;

&lt;p&gt;Relational database-এর ক্ষেত্রে যখন কোনো transaction-এর (এটা নিয়ে এখন bother হওয়ার দরকার নেই) ভেতরে either সবগুলো operation successful হবে or কোনো operation-ই হবে না। যদি fail করে, তাহলে তা automatic rollback হওয়ার feature থাকতে হবে। এই behavior-টাই হলো &lt;strong&gt;Atomicity&lt;/strong&gt;।&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Consistency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;কিছু কিছু public আছে যাদের mind খুব দ্রুত swing হয়। একবার এই তো আরেকবার অন্যটা। এরকমটা যদি আপনার store করা information-এর ওপর হয় তাহলে কী হতে পারে একটু চিন্তা করুন।&lt;br&gt;
Suppose, আপনার system-এ কেউ একজন একটা payment initiate করেছে। এই data-র status swing হচ্ছে, একবার failed, একবার success, কখনো pending। এমন হলে আপনি কি বলতে পারবেন, যে আসলে payment-টা হয়েছে কি না? বলা possible না। এই জন্য database-এ যে value store করেছি সেটা always সেই value provide করতে হবে। এটাই &lt;strong&gt;Consistency&lt;/strong&gt;। সব সময় correct value provide করবে।&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Isolation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;একটা জিনিস চিন্তা করুন, আপনার application-এ same time-এ ২-৩ জন user payment start করলো। Normal ভাবেই এগুলো transaction-এর মধ্যে দিতে হবে। কারণটা তো বুঝতেই পারছেন। এখন ১ জন user-এর একটা problem হওয়ায় একটা operation fail করলো। এই কারণে বাকি user-দের payment-ও fail করলো। এখন আপনার কাছে question, এটা কি ঠিক হলো?&lt;/p&gt;

&lt;p&gt;না, ঠিক হয়নি, তারা তো single user না, তারা আলাদা, সবকিছু আলাদা। তার problem শুধু তার payment-টা failed দেখাবে, বাকিগুলো নিজের মতো চলবে। এটাই তো হওয়া উচিত, তাই নয় কি? এই concept-টাই হচ্ছে Isolation। Isolation প্রত্যেকটা transaction-কে isolate করে রাখে। কেউ কাউকে interfere করতে পারবে না।&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Durability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;একটা scenario চিন্তা করুন, আপনার application-এর একটা user একটা data add করলো। প্রথম ২-৩ দিন সেই data দেখালো কিন্তু ৪ দিনের মাথায় যেয়ে সেই data আর নেই। তাহলে এখন সেই user কি আপনার system use করবে?&lt;br&gt;
এখন মজার বিষয় হচ্ছে, এই data কেউ delete করেনি। System থেকে automatic হারিয়ে গেছে। অনেকটা RAM-এর মতো behavior। Power চলে গেলেই সব ভুলে যাওয়ার মতো অবস্থা।&lt;br&gt;
এখানে solution কী হতে পারে? যাই হয়ে যাক, user-এর data database-এ store থাকতে হবে। এই জিনিসটাই হচ্ছে Durability।&lt;/p&gt;

&lt;p&gt;এই topic-গুলো Relational Database-এর জন্য খুবই important। আমি just একটু idea দেয়ার try করেছি, আপনার mental model-টা create করার try করেছি। আপনার যদি ইচ্ছা হয় তাহলে আপনি পড়তে পারেন। তবে এটুকু বলতে পারি এগুলো আপনাকে ফেলে চলে যাবে না।&lt;/p&gt;


&lt;h2&gt;
  
  
  PostgreSQL কীভাবে Data Store করে?
&lt;/h2&gt;

&lt;p&gt;PostgreSQL data রাখে &lt;strong&gt;pages&lt;/strong&gt; (8KB block) হিসেবে। প্রতিটা table-এর data এই pages-এ থাকে। একটা row যদি multiple pages-এ ছড়িয়ে পড়ে, PostgreSQL সেটা handle করে &lt;strong&gt;TOAST&lt;/strong&gt; mechanism দিয়ে।&lt;/p&gt;


&lt;h2&gt;
  
  
  Index: ডেটাবেসের সূচিপত্র
&lt;/h2&gt;

&lt;p&gt;indexing-এর ব্যবহার তো একটু আগে একবার বলেছি। indexing জিনিসটা আসলে কী সেটা বোঝার try করি চলেন।&lt;/p&gt;

&lt;p&gt;মনে করুন আপনার library আছে, সেখানে হাজার ২-এর মতো বই আছে। এখন আপনার প্রতিনিয়তই কোনো না কোনো বই লাগে। সেই বই খুঁজতে আপনার অর্ধেক time চলে যায়। তো এই problem-এর solution-এর জন্য আপনি চমৎকার কাজ করলেন। আপনি book-এর নামের শব্দের ওপর base করে সাজিয়ে রাখলেন। For example, প্রথম A দিয়ে start হওয়া বইগুলো, then B, then C, এভাবে। এতে সুবিধা কী হবে?&lt;br&gt;
যখন আপনার কোনো বই দরকার হবে তখন, আপনি just সেই বইয়ের letter-এর কাছে চলে যাবেন। ব্যাস আপনার ২৬ ভাগের ২৫ ভাগ কাজ কমে গেলো।&lt;/p&gt;

&lt;p&gt;ঠিক same concept-টা database indexing করার সময় use করে। একটা range তৈরি করে নেয় (for example)। যখন কোনো data insert করা হয় তখন ঐ indexing করা field-টা কোন range-এর ভেতরে যাবে সেটা select করে, ঐ range-এর ভেতরে push করা হয়। এখন ঐ field দিয়ে যখন কোনো query run করা হবে তখন তো সে ঐ range-এর ভেতরে যেয়ে খুঁজে আনবে।&lt;/p&gt;

&lt;p&gt;PostgreSQL indexing-এর জন্য, &lt;strong&gt;B-Tree&lt;/strong&gt; data structure use করে থাকে। এর search complexity অনেকটা binary search-এর মতো।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_users_email&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এখানে users table-এর email field-এ indexing করা হয়েছে। এখন email দিয়ে query অনেক কম সময় নিবে।&lt;/p&gt;

&lt;p&gt;আপাতত এই পর্যন্তই কারণ database indexing নিয়ে একটা dedicated article আসবে।&lt;/p&gt;




&lt;h2&gt;
  
  
  EXPLAIN ANALYZE
&lt;/h2&gt;

&lt;p&gt;মনে করুন একটা system আছে যেখানে ৩-৪ রকমের আলাদা আলাদা system একসাথে মিলে কাজ করছে। এখন কোনো কারণে আপনার application slow হয়ে গেলো। তাহলে বুঝবেন কীভাবে? testing করে। আপনি সবকিছুই check করে দেখলেন, সব ঠিকঠাক। তারপরেও slow। আপনি কি আপনার SQL check করেছেন? আপনার SQL query-তে problem নেই সেটা আপনি sure? এখন হয়তো বলবেন এই তো, sure না।&lt;/p&gt;

&lt;p&gt;এই জিনিসটা বোঝার জন্য default একটা feature থাকে, &lt;strong&gt;EXPLAIN ANALYZE&lt;/strong&gt;। এটার মাধ্যমে আপনার query কোথায়, কীভাবে, কতক্ষণ run হয়েছে তা আপনাকে in-details দিয়ে দিবে। তখন easily determine করতে পারবেন, আসলে SQL-এ problem আছে কি না। নিচে একটা example দেয়া হলো।&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPLAIN&lt;/span&gt; &lt;span class="k"&gt;ANALYZE&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;এটা run করলে বুঝতে পারবেন email-এর জন্য আসলে indexing use হয়েছে কি না।&lt;/p&gt;




&lt;h2&gt;
  
  
  Connection Pool
&lt;/h2&gt;

&lt;p&gt;আপনি যখন কোনো application develop করবেন তখন, backend থেকে database-কে connect করে database থেকে data fetch করবেন। Normal-ভাবে, যখন কোনো data fetch করতে হয় তখন প্রথমেই database connect করতে হয়, then needed operation-গুলো করা হয়। At last connection close করতে হয়। Close না করলে আপনার database server এই connection-গুলো memory-তে store করবে, একসময় যেয়ে দেখা যাবে memory শেষ হয়ে গেছে। আর তখন server crash করবে।&lt;br&gt;
এখানে আরেকটা বিষয় আছে, এখন প্রতিবার connect-disconnect করার কারণে কিছু latency create হচ্ছে। এই latency যদি কমানো যায় তাহলে user experience increase হবে।&lt;/p&gt;

&lt;p&gt;Connection pool-টা হলো এই দুইটার মাঝামাঝি একটা solution। Connection pool জিনিসটা active connection যা always database-এর সাথে connected হয়ে থাকবে। যখন দরকার তখন এই pool use করে data fetch করবে। এই হচ্ছে connection pool-এর basic concept। একটা example দিলে বুঝতে পারবেন।&lt;/p&gt;

&lt;p&gt;মনে করুন আপনি ৫টা connection pool create করেছেন। এর বাইরে database connection-এর আর way নাই (for now)। এখন ৬ জন user একসাথেই request করলো, তখন এই ৫টা connection pool ৫টা user-এর request handle করবে, যখন এই ৫টা user-এর মধ্যে কারো কাজ শেষ হয়ে যাবে তখন ঐ connection pool-টা release হয়ে যাবে। Release হওয়ার সাথে সাথে ৬ নম্বর user-এর request-এ এই connection pool-টা use হয়ে যাবে। আর যদি কোনো request না থাকে তখন connection pool idle হয়ে থাকবে।&lt;/p&gt;

&lt;p&gt;সহজভাবে বললে, connection pool হচ্ছে active database connection, যা always connect হয়ে থাকে। আর database query-এর জন্য এগুলো reuse হয়।&lt;/p&gt;

&lt;p&gt;এখন বলতে পারেন তাহলে connection pool size একটা বড় number দিয়ে দিলে বেশি ভালো হবে? No, it's not like that। বেশি connection দিলে তো 1st situation-এর মতো memory শেষ হয়ে যেতে পারে। এই pool size-টা depend করে আপনার application-এর active user, আপনার database server এর memory + cpu, server এর read/write অপারেশন ইত্যাদি-এর ওপর। তাই pool size ঠিক করার আগে একটু calculation করা প্রয়োজন।&lt;/p&gt;




&lt;h2&gt;
  
  
  বটম লাইন
&lt;/h2&gt;

&lt;p&gt;Database related concept প্রত্যেকটা developer-এর জানা উচিত। কারণ আপনি যত ভালোভাবে আপনার data-কে সাজিয়ে গুছিয়ে securely রাখতে পারবেন + সেগুলো efficiently serve করতে পারবেন, ততই আপনার application বা system-এর performance + longevity বাড়বে।&lt;/p&gt;

&lt;p&gt;যদি আপনি Database নিয়ে আরও বিস্তারিত পড়তে চান তাহলে পরামর্শ হচ্ছে এই বই গুলো পড়ার,&lt;br&gt;
১। Database Management System&lt;br&gt;
২। Database Internals&lt;/p&gt;

&lt;p&gt;একটা মজার কোথা বলি, প্রথম দিকে এই গুলো পড়তে আমার খুবই বোরিং লাগত, কিন্তু যখন একবার এর বেসিক এবং কোর বিষয় গুলো আয়ত্তে করে ফেলবেন তখন তখন আসল মজা টা পাবেন।&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Database is the center point of backend system.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;আপনার সবচেয়ে কঠিন database debugging experience কী ছিল? কমেন্টে শেয়ার করুন! 👇&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>backend</category>
      <category>indexing</category>
    </item>
    <item>
      <title>EC2 Instance Unreachable via SSM Session Manager</title>
      <dc:creator>Rafagross</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:12:04 +0000</pubDate>
      <link>https://dev.to/rafagross/ec2-instance-unreachable-via-ssm-session-manager-1fe9</link>
      <guid>https://dev.to/rafagross/ec2-instance-unreachable-via-ssm-session-manager-1fe9</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This runbook resolves the situation where an EC2 instance is running and visible in the console but either does not appear in the Systems Manager Fleet Manager inventory, or returns a connection error when you attempt to start a Session Manager session.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use This Runbook
&lt;/h2&gt;

&lt;p&gt;Use this runbook when you observe any of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Session Manager shows "Instance not connected" or "Unable to start session"&lt;/li&gt;
&lt;li&gt;The instance does not appear in &lt;strong&gt;Systems Manager → Fleet Manager → Managed Nodes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ssm:StartSession&lt;/code&gt; returns &lt;code&gt;TargetNotConnected&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A previously working instance stopped responding to SSM after a restart, IAM change, or network modification&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Verify Instance State
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; EC2 → Instances → [Instance ID]&lt;/p&gt;

&lt;p&gt;Confirm the instance is in &lt;code&gt;running&lt;/code&gt; state and that both &lt;strong&gt;Status checks&lt;/strong&gt; show 2/2 passed.&lt;/p&gt;

&lt;p&gt;If status checks are failing, stop here and use the EC2 Status Check runbook. SSM is irrelevant if the instance itself is impaired.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Instance state = &lt;code&gt;running&lt;/code&gt;, 2/2 status checks passed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Check SSM Managed Node Status
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; Systems Manager → Fleet Manager → Managed nodes&lt;/p&gt;

&lt;p&gt;Search for the instance ID. If it does not appear, or shows &lt;code&gt;Connection Lost&lt;/code&gt;, the issue is one of: missing IAM role, stopped SSM agent, or blocked network path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Instance appears with status &lt;code&gt;Online&lt;/code&gt;. If missing or &lt;code&gt;Connection Lost&lt;/code&gt;, continue to Step 3.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Verify IAM Instance Profile
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; EC2 → Instances → [Instance ID] → Security tab → IAM Role&lt;/p&gt;

&lt;p&gt;The instance must have an IAM role attached with the &lt;code&gt;AmazonSSMManagedInstanceCore&lt;/code&gt; managed policy (or equivalent custom policy granting the minimum SSM actions).&lt;/p&gt;

&lt;p&gt;Minimum required IAM actions if using a custom policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssm:UpdateInstanceInformation
ssm:ListInstanceAssociations
ssm:DescribeInstanceProperties
ssm:DescribeDocumentParameters
ssmmessages:CreateControlChannel
ssmmessages:CreateDataChannel
ssmmessages:OpenControlChannel
ssmmessages:OpenDataChannel
ec2messages:AcknowledgeMessage
ec2messages:DeleteMessage
ec2messages:FailMessage
ec2messages:GetEndpoint
ec2messages:GetMessages
ec2messages:SendReply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; IAM propagation delay:&lt;br&gt;
IAM role changes applied to a running instance take effect on next SSM agent heartbeat, typically within 2-3 minutes. If you just updated the role, wait 5 minutes and re-check Fleet Manager before continuing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; IAM role attached with &lt;code&gt;AmazonSSMManagedInstanceCore&lt;/code&gt; or equivalent. If missing, attach the role and wait 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Check SSM Agent on the Instance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; EC2 → Instances → [Instance ID] → Actions → Monitor and troubleshoot → Get system log&lt;/p&gt;

&lt;p&gt;Look for lines referencing &lt;code&gt;amazon-ssm-agent&lt;/code&gt;. A healthy agent shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight systemd"&gt;&lt;code&gt;&lt;span class="err"&gt;amazon-ssm-agent.service:&lt;/span&gt; &lt;span class="err"&gt;active&lt;/span&gt; &lt;span class="err"&gt;(running)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Errors to look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Failed to start Amazon SSM Agent&lt;/code&gt; — agent start failure, likely OS-level issue&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Error connecting to endpoint&lt;/code&gt; — network path problem (proceed to Step 5)&lt;/li&gt;
&lt;li&gt;No SSM lines at all — agent not installed or not running&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the agent is not running, you can use EC2 Run Command with &lt;code&gt;AWS-RunShellScript&lt;/code&gt; to restart it — but only if the instance is already registered (partial connectivity). If it's fully unreachable, use EC2 Instance Connect or serial console (if available) to restart manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; SSM agent running. No connection errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Diagnose the Network Path
&lt;/h2&gt;

&lt;p&gt;SSM Session Manager requires outbound HTTPS (port 443) from the EC2 instance to three regional endpoints:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ssm.{region}.amazonaws.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Agent registration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ssmmessages.{region}.amazonaws.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Session data channel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ec2messages.{region}.amazonaws.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;EC2 message delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;For private instances (no NAT Gateway, VPC endpoint required):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; VPC → Endpoints&lt;/p&gt;

&lt;p&gt;Verify that all three interface endpoints exist, are associated with the correct VPC, and have status &lt;code&gt;available&lt;/code&gt;. Check that the endpoint security group allows inbound HTTPS from the instance's security group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; VPC → Security Groups → [Endpoint SG]&lt;/p&gt;

&lt;p&gt;Inbound rule required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPS (443)&lt;/span&gt;
&lt;span class="py"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;[Instance security group ID]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For instances with NAT Gateway:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; VPC → Route Tables → [Instance subnet's route table]&lt;/p&gt;

&lt;p&gt;Confirm a &lt;code&gt;0.0.0.0/0&lt;/code&gt; route pointing to the NAT Gateway exists and the NAT Gateway is in &lt;code&gt;available&lt;/code&gt; state.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
If the instance has a public IP and is in a public subnet with an IGW route, outbound port 443 directly to AWS endpoints is sufficient. No VPC endpoints needed in that case.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Either VPC endpoints present and &lt;code&gt;available&lt;/code&gt;, or valid NAT/IGW route exists. Instance SG allows outbound 443.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Check Instance Security Group Outbound Rules
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; EC2 → Instances → [Instance ID] → Security tab → Security groups → [SG ID] → Outbound rules&lt;/p&gt;

&lt;p&gt;Confirm outbound HTTPS is allowed. The default AWS SG allows all outbound traffic. If rules have been tightened:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPS (443)&lt;/span&gt;
&lt;span class="py"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR (preferred, more restrictive):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPS (443)&lt;/span&gt;
&lt;span class="py"&gt;Destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;[VPC endpoint prefix list or specific endpoint IPs]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected result:&lt;/strong&gt; Outbound 443 allowed from instance security group.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Force SSM Agent Re-Registration (Last Resort)
&lt;/h2&gt;

&lt;p&gt;If all above checks pass but the instance still doesn't appear in Fleet Manager, the agent's registration may be stale (common after AMI snapshots or instance cloning).&lt;/p&gt;

&lt;p&gt;Use EC2 Run Command with &lt;code&gt;AWS-RunShellScript&lt;/code&gt;:&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;# Amazon Linux 2 / AL2023&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl stop amazon-ssm-agent
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/amazon/ssm/registration
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start amazon-ssm-agent
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status amazon-ssm-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait 2 minutes, then re-check Fleet Manager.&lt;/p&gt;




&lt;h2&gt;
  
  
  Validation Checks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;How to Verify&lt;/th&gt;
&lt;th&gt;Expected Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Instance in Fleet Manager&lt;/td&gt;
&lt;td&gt;SSM → Fleet Manager → search instance ID&lt;/td&gt;
&lt;td&gt;Status: Online&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session starts&lt;/td&gt;
&lt;td&gt;SSM → Session Manager → Start session → select instance&lt;/td&gt;
&lt;td&gt;Terminal opens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent heartbeat&lt;/td&gt;
&lt;td&gt;CloudWatch Logs → /aws/ssm/amazon-ssm-agent&lt;/td&gt;
&lt;td&gt;Recent heartbeat log entries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Rollback
&lt;/h2&gt;

&lt;p&gt;No destructive changes are made by this runbook. If you attached a new IAM role that you want to remove:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console path:&lt;/strong&gt; EC2 → Instances → [Instance ID] → Actions → Security → Modify IAM role → No role&lt;/p&gt;




&lt;h2&gt;
  
  
  Escalation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;Next Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All steps pass but instance still unreachable&lt;/td&gt;
&lt;td&gt;Open AWS Support case — provide instance ID, region, VPC endpoint IDs, and CloudWatch agent logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent crashes immediately on start&lt;/td&gt;
&lt;td&gt;Check OS disk space (&lt;code&gt;df -h&lt;/code&gt;), memory, and &lt;code&gt;/var/log/amazon/ssm/amazon-ssm-agent.log&lt;/code&gt; for errors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instance in private subnet, no VPC endpoints, no NAT&lt;/td&gt;
&lt;td&gt;Network path is broken by design — work with network team to add VPC endpoints or NAT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




</description>
      <category>aws</category>
      <category>devops</category>
      <category>linux</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Kimi ครอง Design Arena, แต่แพ้ 4 ใน 5 รอบในคลิปเดียวกัน</title>
      <dc:creator>Nokka</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:10:03 +0000</pubDate>
      <link>https://dev.to/sarantoon/kimi-khrng-design-arena-aetaeph-4-ain-5-rbainkhlipediiywkan-5521</link>
      <guid>https://dev.to/sarantoon/kimi-khrng-design-arena-aetaeph-4-ain-5-rbainkhlipediiywkan-5521</guid>
      <description>&lt;h1&gt;
  
  
  Kimi ครอง Design Arena, แต่แพ้ 4 ใน 5 รอบในคลิปเดียวกัน
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;โดย Nokka (นก-กา) | 12 กันยายน 2026&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;บทความนี้เขียนโดย AI (deepseek-v4.1-flash) ผ่าน Hermes Agent ตรวจสอบและเรียบเรียงโดย Nokka&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ชื่อคลิปบน YouTube บอกว่า "ทำไมนักพัฒนาที่ฉลาดถึงเลือกใช้ Kimi ทำงานออกแบบ" [1]&lt;/p&gt;

&lt;p&gt;คำโปรยของคลิปยิ่งหนักแน่นกว่านั้น&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kimi อยู่บนสุดของ Design Arena เหนือกว่าโมเดลทุกตัวจากค่ายใหญ่ ดังนั้นผมจึงจับ Kimi K3 มาชนกับ Fable และ Astra ในงานออกแบบห้าชิ้น&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ผมดูคลิปนั้นจบ และผลลัพธ์ที่ได้กลับไม่ตรงกับชื่อคลิปเลย&lt;/p&gt;

&lt;h2&gt;
  
  
  วิดีโอนี้ทดสอบอะไร
&lt;/h2&gt;

&lt;p&gt;ช่อง Better Stack มีผู้ติดตาม 202,000 คน เผยแพร่คลิปความยาว 6 นาที 36 วินาที เมื่อวันที่ 12 กันยายน 2026 และมียอดชม 4,632 ครั้งในวันแรก [1]&lt;/p&gt;

&lt;p&gt;การทดสอบคือจับสามโมเดลมาทำงานห้าชิ้นแบบครั้งเดียวจบ หรือ one-shot คือให้โจทย์แล้วใช้ผลลัพธ์ครั้งแรกโดยไม่แก้อะไร [1]&lt;/p&gt;

&lt;p&gt;งานทั้งห้าคือหน้าแลนดิ้ง ฉากสามมิติ ไลบรารีคอมโพเนนต์ แอปมือถือ และเกมที่ต้องสร้างแอสเซตเอง [1]&lt;/p&gt;

&lt;h2&gt;
  
  
  ผลที่ออกมา
&lt;/h2&gt;

&lt;h3&gt;
  
  
  สรุปผลทีละรอบ
&lt;/h3&gt;

&lt;p&gt;ผมสรุปผลทั้งห้ารอบไว้ตรงนี้ เพราะนี่คือส่วนที่ชื่อคลิปไม่ได้เล่า [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;รอบที่หนึ่ง หน้าแลนดิ้ง: Kimi ชนะ&lt;/strong&gt; ได้คำชมเรื่องแอนิเมชัน การจัดตัวอักษร และความลื่นไหลของประสบการณ์ใช้งาน [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;รอบที่สอง ฉากสามมิติ: Astra ชนะ&lt;/strong&gt; ได้ผลลัพธ์ที่กลมกลืนที่สุดเมื่อเทียบกับอีกสองตัวที่ออกมาเป็นบล็อก ๆ [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;รอบที่สาม ไลบรารีคอมโพเนนต์: เสมอกันทั้งสามตัว&lt;/strong&gt; ผู้ทำคลิปบอกว่าคุณภาพใกล้กันจนตัดสินเป็นเรื่องของรสนิยมล้วน ๆ [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;รอบที่สี่ แอปมือถือ: ไม่ให้คะแนนใครเลย&lt;/strong&gt; ผู้ทำคลิปตัดสินว่าทั้งสามตัวได้ผลลัพธ์ที่จืดชืด เป็นบล็อก ๆ และคุณภาพแย่ [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;รอบที่ห้า เกมพร้อมแอสเซต: Claude ชนะ&lt;/strong&gt; ได้แอนิเมชันและรายละเอียดที่เรียบร้อยที่สุด Kimi ได้ที่สอง ส่วน Astra อ่อนที่สุดในรอบนี้ [1]&lt;/p&gt;

&lt;p&gt;นับรวมแล้ว Kimi ชนะหนึ่งรอบ Astra ชนะหนึ่งรอบ Claude ชนะหนึ่งรอบ เสมอหนึ่งรอบ และไม่มีใครชนะหนึ่งรอบ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ไม่มีโมเดลไหนนำใครได้เลย&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  แล้วคำว่า "อยู่บนสุดของ Design Arena" หมายถึงอะไร
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ตัวเลขที่ผมตรวจจากหน้าเว็บจริง
&lt;/h3&gt;

&lt;p&gt;ตอนนี้เป็นส่วนที่ผมไปตรวจสอบเอง เพราะคำกล่าวอ้างนี้ถูกต้องตามข้อมูล แต่ต้องอ่านให้ครบ&lt;/p&gt;

&lt;p&gt;หน้าโปรไฟล์ Kimi K3 บน Design Arena ระบุว่าเป็นโมเดลที่ "ถูกจัดอยู่ในอันดับหนึ่งบ่อยที่สุด" จากทั้งหมด 8,650 การแข่งขัน โดยมีอัตราชนะรวม 64% และคะแนน Elo 1383 [2]&lt;/p&gt;

&lt;p&gt;ตัวเลขรายหมวดน่าสนใจกว่า และตรงกับที่ผมเห็นในคลิป [2]&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;หมวด&lt;/th&gt;
&lt;th&gt;อันดับ&lt;/th&gt;
&lt;th&gt;อัตราชนะ&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;หน้าแลนดิ้ง&lt;/td&gt;
&lt;td&gt;ที่ 1 จาก 172&lt;/td&gt;
&lt;td&gt;61%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;การแสดงข้อมูล&lt;/td&gt;
&lt;td&gt;ที่ 1 จาก 160&lt;/td&gt;
&lt;td&gt;64%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ฉากสามมิติ&lt;/td&gt;
&lt;td&gt;ที่ 2 จาก 152&lt;/td&gt;
&lt;td&gt;69%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;แอปมือถือ&lt;/td&gt;
&lt;td&gt;ที่ 2 จาก 159&lt;/td&gt;
&lt;td&gt;58%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;เกม&lt;/td&gt;
&lt;td&gt;ที่ 3 จาก 164&lt;/td&gt;
&lt;td&gt;63%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ไลบรารี UI&lt;/td&gt;
&lt;td&gt;ที่ 4 จาก 159&lt;/td&gt;
&lt;td&gt;63%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;ดูตามนี้จะเห็นว่าคำกล่าวอ้างในคลิปถูกต้อง เพราะ Kimi ครองอันดับหนึ่งในหมวดหน้าแลนดิ้งและการแสดงข้อมูลจริง และอยู่อันดับสองหรือสามในหมวดอื่น&lt;/p&gt;

&lt;p&gt;แต่ &lt;strong&gt;"อันดับหนึ่งบ่อยที่สุด" กับการชนะทุกครั้งเป็นคนละเรื่องกัน&lt;/strong&gt; และนั่นคือสิ่งที่คลิปนี้พิสูจน์โดยไม่ตั้งใจ&lt;/p&gt;

&lt;h2&gt;
  
  
  บริบทที่ทำให้เรื่องนี้น่าสนใจขึ้น
&lt;/h2&gt;

&lt;p&gt;Kimi K3 ไม่ได้เพิ่งเป็นที่พูดถึงแค่ใน Design Arena&lt;/p&gt;

&lt;p&gt;The New Stack รายงานว่าเมื่อ Kimi K3 เปิดตัว ภายในไม่กี่ชั่วโมงมันไต่ขึ้นเป็นอันดับหนึ่งบน leaderboard ด้าน frontend coding ของ Arena โดยเอาชนะระบบปิดชั้นนำในผลการประเมินแบบ blind [4]&lt;/p&gt;

&lt;p&gt;และหลายสำนักระบุตรงกันว่าเป็นครั้งแรกที่โมเดลเปิดน้ำหนักขึ้นอันดับหนึ่งบน leaderboard ที่ตัดสินด้วยความชอบของคน [6][7]&lt;/p&gt;

&lt;p&gt;ตัวเลขบน leaderboard หมวด code ของ Arena เองก็ยืนยันทิศทางเดียวกัน โดย Kimi K3 ได้คะแนนเหนือคู่แข่งในกลุ่มโมเดลปิด [5]&lt;/p&gt;

&lt;p&gt;ส่วนคะแนนที่ Vals AI ซึ่งเป็นผู้ทดสอบอิสระวัดได้ Kimi K3 ทำได้ 95.10% บน SWE-bench Verified และ 91.27% บน Vibe Code Bench ซึ่งเป็นชุดย่อยของ Vals Index ทั้งคู่ [8]&lt;/p&gt;

&lt;p&gt;ตัวเลขเหล่านี้ทำให้คำโปรยของคลิปที่ว่า "Kimi อยู่บนสุดของ Design Arena" ไม่ใช่คำกล่าวอ้างลอย ๆ แต่มันเป็นความจริงที่ต้องอ่านให้ถูกบริบท&lt;/p&gt;

&lt;h2&gt;
  
  
  ประเด็นที่ผมคิดว่าสำคัญที่สุด
&lt;/h2&gt;

&lt;p&gt;คำโปรยของคลิปคือ "โมเดลที่คุณจ่ายเงินอยู่ อาจไม่ใช่ตัวที่คุณควรใช้" [1]&lt;/p&gt;

&lt;p&gt;ผมเห็นด้วยกับประโยคนี้ แต่ผมคิดว่าคลิปนี้ให้บทเรียนที่ตรงกว่าตัวเอง&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;งานออกแบบหนึ่งชิ้นไม่ใช่การวัดที่แม่นพอจะบอกว่าโมเดลไหนเก่งกว่า&lt;/strong&gt; เพราะหนึ่งชิ้นงานมีตัวแปรเยอะ ทั้งการสุ่มของโมเดล ลักษณะโจทย์ และความชอบส่วนตัวของผู้ตัดสิน&lt;/p&gt;

&lt;p&gt;นี่คือเหตุผลว่าทำไม leaderboard ถึงใช้การแข่งขันหลายพันครั้งในการจัดอันดับ แต่คลิปใช้แค่ห้าครั้ง&lt;/p&gt;

&lt;p&gt;ทั้งสองแบบมีประโยชน์ต่างกัน &lt;strong&gt;leaderboard บอกว่าค่าเฉลี่ยของโมเดลอยู่ตรงไหน ส่วนการทดสอบห้าชิ้นบอกว่าครั้งนี้เกิดอะไรขึ้น&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ถ้าผลออกมาไม่ตรงกัน สิ่งที่ผิดไม่ใช่ข้อมูลชุดใดชุดหนึ่ง แต่วิธีที่เราเอาข้อมูลชุดหนึ่งไปสรุปอีกชุดหนึ่งต่างหาก&lt;/p&gt;

&lt;h2&gt;
  
  
  ปัญหาทางเทคนิคของคลิปเอง
&lt;/h2&gt;

&lt;p&gt;ช่องนี้เปิดให้แสดงความคิดเห็น และมีข้อวิจารณ์หนึ่งที่ตรงประเด็น&lt;/p&gt;

&lt;p&gt;ผู้ชมคนหนึ่งตั้งข้อสังเกตว่าคลิปไม่ได้ระบุชื่อโมเดลที่ใช้อย่างชัดเจน [1]&lt;/p&gt;

&lt;p&gt;ผมตรวจสอบแล้วพบว่าเรื่องนี้เป็นจริงในระดับหนึ่ง คลิปใช้ชื่อ "Kimi", "Claude" และ "Astra" ลอย ๆ โดยไม่บอกเวอร์ชันของแต่ละตัวในเนื้อหาหลัก&lt;/p&gt;

&lt;p&gt;สำหรับ Claude คลิปไม่ได้บอกว่าใช้ Fable 5.1 หรือรุ่นไหน ส่วนคำโปรยบอกว่า "Fable และ Astra" แต่ในเนื้อหาพูดถึง Astra ในฐานะ GPT-6 Astra [1][3]&lt;/p&gt;

&lt;p&gt;จุดนี้สำคัญเพราะเมื่อไม่ระบุเวอร์ชัน ผลการทดสอบจะเปรียบเทียบกับอะไรก็ไม่รู้ และไม่มีใครทำซ้ำได้&lt;/p&gt;

&lt;h2&gt;
  
  
  ข้อวิจารณ์ที่ผมคิดว่าน้ำหนักดีที่สุด
&lt;/h2&gt;

&lt;p&gt;ในคอมเมนต์ใต้คลิป มีผู้ชมเขียนไว้ประมาณว่า [1]&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;เวลาโมเดลใหม่เปิดตัว ทุกคนจับจ้องแต่ส่วนติดต่อผู้ใช้ ทั้งที่ส่วนติดต่อไม่ใช่งานวิศวกรรมจริง ๆ ตรรกะที่อยู่ข้างในต่างหากที่สำคัญ ส่วนที่เห็นสวย ๆ มีประโยชน์แค่ในงานโชว์และพอร์ตโฟลิโอ&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;ผมคิดว่าคอมเมนต์นี้ตรงกับสิ่งที่ผมเห็นในคลิปมาก เพราะห้าจานทดสอบของคลิปนี้เป็นงานที่มองเห็นผลทันทีทั้งหมด ไม่มีงานที่ต้องแก้บั๊กซับซ้อนหรือดูแลโค้ดระยะยาวเลย [1]&lt;/p&gt;

&lt;p&gt;ผลจากการวัดแบบนี้จึงบอกความสามารถเรื่องหน้าตาได้ดี แต่บอกความสามารถเรื่องความทนทานของโค้ดไม่ได้&lt;/p&gt;

&lt;h2&gt;
  
  
  มุมมองจากคนที่ทำงานกับโมเดลทุกวัน
&lt;/h2&gt;

&lt;p&gt;ผมเจอสถานการณ์แบบนี้ตลอด เพราะผมเลือกโมเดลตามงาน ไม่ได้เลือกตามอันดับ&lt;/p&gt;

&lt;p&gt;โมเดลที่ตัวเลขสูงสุดบน leaderboard อาจเขียนงานประเภทนี้ได้แย่กว่าโมเดลที่อันดับต่ำกว่าสองสามอันดับ เพราะความถนัดเฉพาะทางของแต่ละตัวต่างกันจริง&lt;/p&gt;

&lt;p&gt;สิ่งที่ผมทำเวลาอ่านผลทดสอบคือถามสามข้อ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;หนึ่ง งานที่ทดสอบเหมือนงานที่ผมจะทำไหม&lt;/strong&gt; งานออกแบบหน้าแลนดิ้งกับงานเขียนบทความยาวเป็นคนละทักษะ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;สอง ทดสอบกี่ครั้ง&lt;/strong&gt; ห้าครั้งต่างจากแปดพันครั้งมาก และผลที่ได้ควรถูกอ่านให้ต่างกัน&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;สาม ผู้ตัดสินเป็นใคร&lt;/strong&gt; ถ้าเป็นคนเดียว ความชอบส่วนตัวของคน ๆ นั้นคือตัวแปรที่ใหญ่ที่สุดในผลลัพธ์&lt;/p&gt;

&lt;h2&gt;
  
  
  สิ่งที่ทำได้ตั้งแต่วันนี้
&lt;/h2&gt;

&lt;h3&gt;
  
  
  วิธีอ่านผลทดสอบให้เป็น
&lt;/h3&gt;

&lt;p&gt;อย่างแรก ถ้าคุณเห็นคลิปหรือโพสต์ที่บอกว่าโมเดลหนึ่งชนะ ให้ดูจำนวนงานที่ทดสอบก่อน ถ้าน้อยกว่าสิบครั้ง ให้อ่านเป็นกรณีศึกษา ไม่ใช่การจัดอันดับ&lt;/p&gt;

&lt;p&gt;อย่างที่สอง ถ้าคุณใช้ AI ออกแบบงานจริง ลองทดสอบกับงานของคุณเองสักห้าชิ้นแล้วตัดสิน โดยใช้ leaderboard เป็นแค่ตัวช่วยกรองตัวเลือกแรก ไม่ใช่คำตัดสินสุดท้าย [2]&lt;/p&gt;

&lt;p&gt;อย่างที่สาม ระวังการจับคู่ชื่อคลิปกับคำโปรย เพราะชื่อคลิปเป็นเรื่องการตลาด ส่วนคำโปรยเป็นเรื่องของคนทำคลิปที่ต้องขายไอเดีย และส่วนที่บอกความจริงคือเนื้อหาข้างใน&lt;/p&gt;

&lt;h2&gt;
  
  
  ข้อควรระวัง
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;หนึ่ง&lt;/strong&gt; ผมไม่ได้ดูวิดีโอทั้งคลิปด้วยเสียงของตัวเอง เพราะ YouTube บล็อกการเข้าถึงจากเซิร์ฟเวอร์ที่ผมใช้ดึงข้อมูล สิ่งที่ผมอ่านได้คือชื่อคลิป คำโปรย บทบรรยาย และคอมเมนต์ที่แสดงบนหน้าเว็บ ซึ่งรวมผลการตัดสินทั้งห้ารอบและช่วงเวลาของแต่ละรอบ [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;สอง&lt;/strong&gt; ผมไม่ทราบว่าโมเดลที่ใช้ในแต่ละรอบเป็นเวอร์ชันใดแน่ชัด คลิปใช้ชื่อ Kimi, Claude และ Astra โดยไม่ระบุเวอร์ชันในเนื้อหาหลัก และนี่เป็นข้อจำกัดที่ผมวิจารณ์ไว้ในบทความเองด้วย [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;สาม&lt;/strong&gt; ตัวเลข Design Arena ที่ผมยกมาเป็นข้อมูล ณ วันที่ 12 กันยายน 2026 ซึ่งเป็นวันเดียวกับที่คลิปเผยแพร่ และเป็นวันที่ผมตรวจหน้าเว็บ ตัวเลขนี้เปลี่ยนได้ทุกวันตามการแข่งขันใหม่ [2]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;สี่&lt;/strong&gt; ผมพบว่าชื่อ Astra และ Fable ที่คลิปใช้ ตรงกับโมเดลจริงที่เปิดตัวต้นเดือนกันยายน 2026 คือ GPT-6 Astra ของ OpenAI และ Claude Fable 5.1 ของ Anthropic [9] แต่ผมไม่ยืนยันว่าคลิปใช้เวอร์ชันหรือค่าระดับความพยายามใดในการทดสอบ เพราะคลิปไม่ระบุ [1]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ห้า&lt;/strong&gt; ข้อวิจารณ์ในคอมเมนต์ที่ผมยกมาเป็นความเห็นของผู้ชม ไม่ใช่ข้อเท็จจริงที่ตรวจสอบได้ และผมไม่ได้ยืนยันว่าผู้เขียนคอมเมนต์ทำงานในวงการนี้หรือไม่ [1]&lt;/p&gt;

&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;คลิปนี้ตั้งชื่อว่า "ทำไมนักพัฒนาที่ฉลาดถึงเลือก Kimi" แต่เนื้อหาข้างในกลับแสดงให้เห็นว่า Kimi ชนะหนึ่งในห้ารอบเท่ากับคู่แข่งอีกสองตัว&lt;/p&gt;

&lt;p&gt;ผมไม่คิดว่านี่เป็นข้อบกพร่องของคนทำคลิป เพราะคำโปรยของเขาบอกไว้ตรง ๆ ว่าอยากให้คนตั้งคำถามกับโมเดลที่ตัวเองจ่ายเงินอยู่ [1]&lt;/p&gt;

&lt;p&gt;แต่ผมคิดว่านี่คือบทเรียนที่ดีกว่าที่คลิปตั้งใจจะสอน นั่นคือ &lt;strong&gt;อันดับหนึ่งบน leaderboard กับการชนะในงานที่คุณกำลังทำอยู่ เป็นสองเรื่องที่แยกกัน&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;คำถามที่ผมคิดว่าควรถามเวลาอ่านผลทดสอบแบบนี้คือ ถ้าผลออกมาตรงข้ามกับที่คุณคาด คุณจะเชื่อตัวเลข หรือเชื่องานที่วางอยู่ตรงหน้าคุณ&lt;/p&gt;

&lt;p&gt;ถ้าคุณเคยเจอเคสแบบนี้ คือผลทดสอบบอกอย่าง แต่ใช้งานจริงได้อีกอย่าง ลองแชร์ให้ผมฟังได้ เพราะกรณีแบบนั้นสอนได้มากกว่าตัวเลขบน leaderboard&lt;/p&gt;

&lt;h2&gt;
  
  
  แหล่งอ้างอิง
&lt;/h2&gt;

&lt;p&gt;[1] Better Stack, "Why Smart Developers Use Kimi For Design" (YouTube, 12 ก.ย. 2026), &lt;a href="https://www.youtube.com/watch?v=zx9xhp7wB9M" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=zx9xhp7wB9M&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] Design Arena, โปรไฟล์และอันดับของ Kimi K3 (สืบค้น 12 ก.ย. 2026), &lt;a href="https://www.designarena.ai/models/kimi-k3" rel="noopener noreferrer"&gt;https://www.designarena.ai/models/kimi-k3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] Design Arena, รายชื่อโมเดลที่ประเมิน (สืบค้น 12 ก.ย. 2026), &lt;a href="https://www.designarena.ai/models" rel="noopener noreferrer"&gt;https://www.designarena.ai/models&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] The New Stack, "Kimi K3 tops Arena's coding leaderboard and it's open-weight" (2026), &lt;a href="https://thenewstack.io/kimi-k3-open-weight-coding/" rel="noopener noreferrer"&gt;https://thenewstack.io/kimi-k3-open-weight-coding/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] Design Arena, leaderboard หมวด Code (สืบค้น 12 ก.ย. 2026), &lt;a href="https://www.designarena.ai/leaderboard/code" rel="noopener noreferrer"&gt;https://www.designarena.ai/leaderboard/code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[6] Kilo, "Kimi K3 Just Took the #1 Spot for Frontend. We Put It Against Claude Fable 5 on 10 UIs" (2026), &lt;a href="https://blog.kilo.ai/p/kimi-k3" rel="noopener noreferrer"&gt;https://blog.kilo.ai/p/kimi-k3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[7] Data Science Dojo, "Kimi K3 vs Claude Fable 5: Benchmarks compared" (2026), &lt;a href="https://datasciencedojo.com/blog/kimi-k3-vs-claude-fable-5/" rel="noopener noreferrer"&gt;https://datasciencedojo.com/blog/kimi-k3-vs-claude-fable-5/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[8] Vals AI, ผลการประเมิน Kimi K3 บน Vals Index (16 ก.ค. 2026), &lt;a href="https://www.vals.ai/models/kimi_kimi-k3" rel="noopener noreferrer"&gt;https://www.vals.ai/models/kimi_kimi-k3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[9] DataCamp, "GPT-6 Astra vs Claude Fable 5.1: Benchmarks and Pricing" (ก.ย. 2026), &lt;a href="https://www.datacamp.com/blog/gpt-6-astra-vs-claude-fable-5-1" rel="noopener noreferrer"&gt;https://www.datacamp.com/blog/gpt-6-astra-vs-claude-fable-5-1&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>design</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Designing a deterministic browser-side photo analysis flow</title>
      <dc:creator>chang zhong</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:05:45 +0000</pubDate>
      <link>https://dev.to/chang_zhong_2c82ccf7fb888/designing-a-deterministic-browser-side-photo-analysis-flow-2e2c</link>
      <guid>https://dev.to/chang_zhong_2c82ccf7fb888/designing-a-deterministic-browser-side-photo-analysis-flow-2e2c</guid>
      <description>&lt;p&gt;Photo-analysis products are easy to make look more certain than they are. A single number can feel authoritative even when the user has no way to tell what changed between two runs, where the calculation happened, or whether their image left the device.&lt;/p&gt;

&lt;p&gt;While building a small browser-based facial-proportion tool, I found that a few engineering choices matter more than adding another model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the calculation repeatable
&lt;/h2&gt;

&lt;p&gt;The pipeline starts with 478 detected facial landmarks and derives four displayed proportions: harmony, symmetry, eye area, and jawline. The important constraint is that the scoring formula is fixed. Given the same landmarks, it produces the same output.&lt;/p&gt;

&lt;p&gt;That sounds ordinary, but it changes how a result can be discussed. A user can repeat a run after changing the photo and know that a changed score came from changed measurable input, not a different sampling path or an opaque model response. It also makes debugging possible: the ratio behind each score can be displayed alongside the score instead of asking users to trust a label.&lt;/p&gt;

&lt;p&gt;Repeatability does not make a score universally meaningful. It only makes the mechanism inspectable. In this case, the tier labels are still being calibrated against real photos, so the labels may move as the calibration set grows. Keeping that limitation visible is part of the interface, not a footnote for later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reject bad input before calculating
&lt;/h2&gt;

&lt;p&gt;A deterministic formula still produces misleading output if the input photo is unsuitable. The browser checks angle, sharpness, exposure, framing, and face size before the scoring step. A photo that does not meet those conditions should be rejected with a useful reason, not pushed through so the product can always return a number.&lt;/p&gt;

&lt;p&gt;This is a product decision as much as an engineering one. A refusal is less satisfying than a result, but it makes the boundary of the system legible. It also prevents a score from being mistaken for advice or a medical conclusion. The tool measures image-derived proportions; it does not recommend treatments, surgery, or behavior changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the image as local data
&lt;/h2&gt;

&lt;p&gt;For a tool that starts with a face photo, the default data path should be easy to explain. Detection and scoring run in the browser, and the uploaded image is read locally rather than sent to an application server. If a user chooses to share a result, the shared record contains the four scores and photo-quality values, not the original image or landmark coordinates.&lt;/p&gt;

&lt;p&gt;Local processing does not remove every privacy question, but it narrows the one users care about first: whether a personal photo has to leave the device to get a measurement. Making that answer simple also keeps the system architecture simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  The useful takeaway
&lt;/h2&gt;

&lt;p&gt;For small analysis tools, reliability often comes from making fewer promises. A fixed calculation, visible inputs, a clear rejection path, and a local-first data flow give users something they can inspect and repeat. They do not turn a measurement into a verdict.&lt;/p&gt;

&lt;p&gt;The working product is &lt;a href="https://looksmaxscale.com/" rel="noopener noreferrer"&gt;Looksmax Scale&lt;/a&gt;. I am its builder; the link is included as a concrete implementation reference, not as a substitute for the article.&lt;/p&gt;

&lt;p&gt;Disclosure: this post was drafted with AI assistance and reviewed by the product builder.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stop Making Your React Components Reusable | React Design</title>
      <dc:creator>Nainik Mehta</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:01:21 +0000</pubDate>
      <link>https://dev.to/nainikmehta/stop-making-your-react-components-reusable-react-design-4086</link>
      <guid>https://dev.to/nainikmehta/stop-making-your-react-components-reusable-react-design-4086</guid>
      <description>&lt;h2&gt;
  
  
  The Reusability Trap: Why Your React Components Are Becoming Unmaintainable
&lt;/h2&gt;

&lt;p&gt;In the modern React ecosystem, "reusability" has been elevated from a best practice to a full-blown theology. We are taught from our first tutorial that DRY (Don't Repeat Yourself) is the ultimate virtue. If you write the same button twice, you’ve failed. If you copy-paste a layout block, you’re a junior developer.&lt;/p&gt;

&lt;p&gt;But this obsession with premature abstraction is quietly killing our codebases. In our relentless quest for perfect React component design, we have fallen victim to "componentitis"—the tendency to abstract UI elements for hypothetical future needs that, nine times out of ten, never actually materialize.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Symptom: The "God Component"
&lt;/h2&gt;

&lt;p&gt;We have all seen it. A component that starts its life as a simple &lt;code&gt;Card&lt;/code&gt; eventually morphs into a fragile, sprawling web of conditional props. It starts with &lt;code&gt;showIcon&lt;/code&gt;, then adds &lt;code&gt;isHeaderCompact&lt;/code&gt;, then &lt;code&gt;disableShadow&lt;/code&gt;, until you are staring at an API that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Card&lt;/span&gt; 
  &lt;span class="na"&gt;showIcon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
  &lt;span class="na"&gt;isHeaderCompact&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
  &lt;span class="na"&gt;disableShadow&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
  &lt;span class="na"&gt;hasWarningBorder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"md"&lt;/span&gt;
  &lt;span class="c1"&gt;// ...and 15 more props&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not component design; this is configuration. Every new boolean prop you add creates an exponential matrix of untested UI states. When you have five boolean props, you don't just have five features; you have 32 potential combinations of states. Most of those combinations are never tested, never used, and eventually, they break in ways that are impossible to debug. This is the definition of a "God Component"—a fragile, monolithic entity that everyone is afraid to touch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Root Cause: Solving Problems That Don't Exist
&lt;/h2&gt;

&lt;p&gt;The core issue is that we are designing for a future that hasn't happened yet. We are trying to build a "universal" component that can handle every possible edge case, just in case we need it later. This violates the core principle of YAGNI (You Aren't Gonna Need It).&lt;/p&gt;

&lt;p&gt;When we force reusability where it doesn't belong, we increase the cognitive load for every other developer on the team. To use a component, they now have to read through a massive prop-types definition or TypeScript interface to understand which combination of flags will render the specific UI they need.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: A Pragmatic Taxonomy
&lt;/h2&gt;

&lt;p&gt;Instead of striving for maximum reusability, we should aim for &lt;em&gt;appropriate&lt;/em&gt; reusability. I suggest categorizing your components into three distinct buckets:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Universal Primitives
&lt;/h3&gt;

&lt;p&gt;These are your building blocks. They are highly reusable, contain minimal styles, and share core behavioral logic. Think &lt;code&gt;Button&lt;/code&gt;, &lt;code&gt;Input&lt;/code&gt;, &lt;code&gt;Checkbox&lt;/code&gt;, or &lt;code&gt;Typography&lt;/code&gt;. These components are allowed to be highly configurable because their scope is narrow and well-defined.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Global Patterns
&lt;/h3&gt;

&lt;p&gt;These are app-specific constraints. They handle complex interactions that need to be consistent across the entire application. Think &lt;code&gt;Modal&lt;/code&gt;, &lt;code&gt;Navigation&lt;/code&gt;, or &lt;code&gt;ToastContainer&lt;/code&gt;. These are reusable, but they are bounded by your application's specific design system.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. View Components
&lt;/h3&gt;

&lt;p&gt;These are your feature-specific components. They are strictly non-reusable. If you need a &lt;code&gt;UserDashboardProfileCard&lt;/code&gt;, build it for the dashboard. If you need a similar card for the &lt;code&gt;Settings&lt;/code&gt; page, do not try to merge them. Let them be "duplicate" and simple. If you find yourself needing to reuse them later, that is the perfect time to refactor—not before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Favor Composition Over Configuration
&lt;/h2&gt;

&lt;p&gt;When you do need flexibility, stop reaching for more props. Instead, favor composition. React’s &lt;code&gt;children&lt;/code&gt; prop and dedicated "slots" (passing components as props) are powerful tools that allow you to inject behavior and structure without polluting the parent component's API.&lt;/p&gt;

&lt;p&gt;By keeping feature-specific code in its own folder and embracing duplication as a temporary state, you keep your components lean, testable, and, most importantly, maintainable. The next time you find yourself adding a prop to a component to satisfy a "what if" scenario, stop. Build it twice, see how it evolves, and only abstract when the pattern is undeniable. &lt;/p&gt;

&lt;p&gt;Your future self (and your teammates) will thank you.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>coding</category>
    </item>
    <item>
      <title>When a Zero-Parameter Cache Overtakes a Transformer</title>
      <dc:creator>Seth Wheeler</dc:creator>
      <pubDate>Sun, 13 Sep 2026 03:00:00 +0000</pubDate>
      <link>https://dev.to/megapixel99/when-a-zero-parameter-cache-overtakes-a-transformer-37c6</link>
      <guid>https://dev.to/megapixel99/when-a-zero-parameter-cache-overtakes-a-transformer-37c6</guid>
      <description>&lt;p&gt;The question this series exists to answer, put in a form that can be measured: a transformer sees a fixed 64-token window, a count table over the current document sees the whole document, and as documents get longer, how much of the trained model does the free mechanism replace?&lt;/p&gt;

&lt;p&gt;An earlier experiment had established that the document cache is worth up to +0.106 top-1 on a long coherent document, against +0.014 for every improvement to corpus modelling from Witten-Bell all the way to &lt;a href="https://sethwheeler.dev/blog/hpylm-slope/" rel="noopener noreferrer"&gt;a full Gibbs-sampled hierarchical Pitman-Yor model&lt;/a&gt;. But that comparison had no neural network in it, so it could not ask the question that matters. This one does: six systems, identical positions, one continuous text cut into documents of length L so that length and coherence grow together. The research repo is not public, so the numbers come from its own harness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The table
&lt;/h2&gt;

&lt;p&gt;Out of distribution, 1.43M-parameter transformer, 64-token window.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;system&lt;/th&gt;
&lt;th&gt;params&lt;/th&gt;
&lt;th&gt;L=60&lt;/th&gt;
&lt;th&gt;L=250&lt;/th&gt;
&lt;th&gt;L=1000&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;corpus only, WB-4 on 4M tokens&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0.128&lt;/td&gt;
&lt;td&gt;0.129&lt;/td&gt;
&lt;td&gt;0.124&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;cache only&lt;/strong&gt;, this document and nothing else&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.103&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.172&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.213&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;corpus + cache, &lt;strong&gt;no neural network&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0.139&lt;/td&gt;
&lt;td&gt;0.201&lt;/td&gt;
&lt;td&gt;0.228&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;transformer only&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.43M&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.152&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.143&lt;/td&gt;
&lt;td&gt;0.149&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transformer + corpus&lt;/td&gt;
&lt;td&gt;1.43M&lt;/td&gt;
&lt;td&gt;0.147&lt;/td&gt;
&lt;td&gt;0.156&lt;/td&gt;
&lt;td&gt;0.153&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transformer + corpus + cache&lt;/td&gt;
&lt;td&gt;1.43M&lt;/td&gt;
&lt;td&gt;0.161&lt;/td&gt;
&lt;td&gt;0.214&lt;/td&gt;
&lt;td&gt;0.230&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Paired tests on the headline comparison, same positions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;L=60    transformer 0.152  cache 0.103  delta -0.050  CI [-0.067,-0.032]  SIGNIFICANT (transformer)
L=250   transformer 0.143  cache 0.172  delta +0.029  CI [+0.010,+0.049]  SIGNIFICANT (cache)
L=1000  transformer 0.149  cache 0.213  delta +0.064  CI [+0.044,+0.083]  SIGNIFICANT (cache)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test reports both directions, because a confidence interval entirely below zero is a significant win for the transformer, and describing that as "not significant" would be wrong. At L=60 the transformer wins and the write-up says so.&lt;/p&gt;

&lt;h2&gt;
  
  
  One mechanism is flat and the other is not
&lt;/h2&gt;

&lt;p&gt;The transformer goes 0.152, 0.143, 0.149 across the three lengths. No trend, and the reason is structural rather than statistical: a 64-token window makes a 1000-token document literally invisible. The cache goes 0.103, 0.172, 0.213; it doubles.&lt;/p&gt;

&lt;p&gt;Document length is a resource one mechanism can spend and the other cannot, and that is the entire result in a line. Everything below is arithmetic on it.&lt;/p&gt;

&lt;p&gt;The crossover is early. Below roughly 100 tokens the trained model wins decisively. Somewhere between 60 and 250 tokens a count table built over the current document, with no parameters, no training and a construction cost in microseconds, overtakes 1.43 million trained parameters, and by 1000 tokens it wins by 0.064 top-1, a 43% relative margin.&lt;/p&gt;

&lt;p&gt;These are also genuinely different mechanisms rather than two variants of one. The two systems disagree on 20 to 25% of positions, against the 3% seen between two hybrids in an earlier experiment. They are not converging on the same predictions by different routes. They disagree, and one of them is right more often as the document grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  The parameters stop contributing
&lt;/h2&gt;

&lt;p&gt;What adding the transformer buys on top of corpus plus cache:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;L=60&lt;/th&gt;
&lt;th&gt;L=250&lt;/th&gt;
&lt;th&gt;L=1000&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;gain from adding 1.43M parameters&lt;/td&gt;
&lt;td&gt;+0.022&lt;/td&gt;
&lt;td&gt;+0.013&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+0.002&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At L=60 the transformer is carrying real weight; at L=1000 it contributes 0.002 top-1 on top of two count tables, and the substitution is close to complete.&lt;/p&gt;

&lt;p&gt;The mixture weights agree without being told to. The cache's optimal weight climbs from 0.25 to 0.70 to 0.85 as documents lengthen, so at L=1000 the best system is 85% document and 15% corpus. That is a fitted parameter arriving at the same conclusion as the ablation, which is the sort of agreement worth more than either alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not say
&lt;/h2&gt;

&lt;p&gt;It says nothing about a model whose context window covers the document. The comparison is &lt;em&gt;parameters at a fixed short context&lt;/em&gt; against &lt;em&gt;a count table over the document&lt;/em&gt;, which is the realistic small-model setting and the one this project's tools actually live in. A long-context model would read the document itself, and this experiment cannot see that at all.&lt;/p&gt;

&lt;p&gt;It also does not escape the finding it sits next to. Counting still does not scale with corpus data; &lt;a href="https://sethwheeler.dev/blog/hpylm-slope/" rel="noopener noreferrer"&gt;that axis is closed&lt;/a&gt;. What scales here is the amount of &lt;em&gt;current document&lt;/em&gt; available, which is a different axis, and this experiment says the returns are on the second one.&lt;/p&gt;

&lt;p&gt;And it is out of distribution by construction: a Gutenberg book against a TinyStories corpus model and a TinyStories transformer. Both trained components face the same shift, so the comparison is internally fair, and an earlier finding already said the cache pays most out of distribution. In-domain the transformer would be stronger and the crossover would move right. Measuring that needs a long-document in-domain corpus, which this project does not have, and it is the clearest gap in this line of work.&lt;/p&gt;

&lt;p&gt;Two smaller caveats belong with the numbers rather than after them. The L=1000 cell has 74 documents and is the noisiest of the three. And the cache at L=60 has a high top-5 of 0.546 alongside its low top-1, because a 60-token document supplies about 30 distinct types, so the distribution is concentrated on a few candidates without being right about which. That is a real property of a short document rather than an artefact, and it inverts as documents lengthen.&lt;/p&gt;

&lt;h2&gt;
  
  
  What generalises
&lt;/h2&gt;

&lt;p&gt;The useful shape here is not "counting beats neural networks", which is not what the table says at any length below about 100 tokens. It is that two mechanisms can look like competitors while depending on completely different resources, and that comparing them at one operating point tells you almost nothing.&lt;/p&gt;

&lt;p&gt;At L=60 the honest headline is that a 1.43M-parameter transformer beats a zero-parameter cache by a significant margin. At L=1000 the honest headline is the reverse, by a larger one. Both were measured on the same day with the same harness; either could have been published alone.&lt;/p&gt;

&lt;p&gt;The general version: before comparing two systems, find the axis one of them can spend and the other cannot, then measure along it. If you cannot name that axis, you are probably measuring at whichever point you happened to build first.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>llm</category>
    </item>
    <item>
      <title>O que é Cloud Computing? (A visão de um estudante de tecnologia)</title>
      <dc:creator>Davi Pereira</dc:creator>
      <pubDate>Sun, 13 Sep 2026 02:58:16 +0000</pubDate>
      <link>https://dev.to/davi_pereira2z/o-que-e-cloud-computing-a-visao-de-um-estudante-de-tecnologia-4okc</link>
      <guid>https://dev.to/davi_pereira2z/o-que-e-cloud-computing-a-visao-de-um-estudante-de-tecnologia-4okc</guid>
      <description>&lt;p&gt;Olá, pessoal! Sou o Davi.&lt;/p&gt;

&lt;p&gt;Este é o meu &lt;strong&gt;primeiro artigo no DEV Community&lt;/strong&gt;. Sou estudante universitário da área de tecnologia e decidi começar a escrever para fixar o que venho aprendendo nas aulas e nos estudos individuais.&lt;/p&gt;

&lt;p&gt;Quando comecei a estudar, ouvia falar sobre "Nuvem" ou "Cloud Computing" a todo momento, mas o termo parecia meio abstrato. Se você também está no início da faculdade ou migrando para a área e quer entender esse conceito sem complicação, este post é para você!&lt;/p&gt;




&lt;h2&gt;
  
  
  A frase que fez o "estalo" nos meus estudos
&lt;/h2&gt;

&lt;p&gt;No começo, a palavra "nuvem" faz parecer algo invisível solto no ar. Mas a definição mais simples que encontrei no início das minhas leituras foi:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A nuvem é apenas o computador de outra pessoa ao qual você se conecta pela internet."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Em termos práticos, &lt;strong&gt;Cloud Computing&lt;/strong&gt; é o aluguel de recursos computacionais — como servidores, armazenamento de arquivos e bancos de dados — através da internet. &lt;/p&gt;

&lt;p&gt;Em vez de uma empresa (ou você) comprar um servidor físico caro, colocar na sala e pagar pela energia/manutenção, você simplesmente contrata a capacidade computacional de grandes provedores (como AWS, Google Cloud ou Azure).&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparando o modelo tradicional com a Nuvem
&lt;/h2&gt;

&lt;p&gt;Para entender por que isso virou o padrão da indústria, me ajudou muito fazer essa comparação direta:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Comprar Servidor Próprio&lt;/th&gt;
&lt;th&gt;Usar Computação em Nuvem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Alto custo inicial para comprar hardware&lt;/td&gt;
&lt;td&gt;Zero investimento inicial em equipamentos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Demora para comprar e instalar novas peças se o sistema crescer&lt;/td&gt;
&lt;td&gt;Aumenta ou diminui a capacidade em segundos pela internet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Você cuida do ar-condicionado, energia e manutenção física&lt;/td&gt;
&lt;td&gt;O provedor cuida de toda a infraestrutura física&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custo fixo, mesmo se ninguém estiver usando o sistema&lt;/td&gt;
&lt;td&gt;Pagamento por uso (paga apenas pelo que consome)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Os 3 níveis da Nuvem (A analogia da moradia)
&lt;/h2&gt;

&lt;p&gt;Nos cursos e disciplinas de infraestrutura, aprendemos que a nuvem se divide em três modelos principais. Uma analogia simples me ajudou a memorizar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IaaS (Infraestrutura como Serviço):&lt;/strong&gt; É como alugar um &lt;strong&gt;apartamento vazio&lt;/strong&gt;. Você recebe a estrutura bruta (servidor e rede) e precisa instalar o sistema operacional e configurar tudo do seu jeito.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PaaS (Plataforma como Serviço):&lt;/strong&gt; É como alugar um &lt;strong&gt;quarto mobiliado&lt;/strong&gt;. O ambiente para rodar o código já vem pronto; você só precisa enviar seu programa e mandar executar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SaaS (Software como Serviço):&lt;/strong&gt; É como se hospedar em um &lt;strong&gt;hotel&lt;/strong&gt;. O sistema está 100% pronto para uso e você só acessa pelo navegador ou aplicativo. &lt;em&gt;(Ex: Google Drive, Notion, Canva)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Entender a nuvem me fez perceber que, hoje em dia, tão importante quanto escrever código é saber onde e como esse código vai rodar quando estiver pronto para os usuários.&lt;/p&gt;

&lt;p&gt;Como este é meu primeiro texto e ainda estou na jornada de aprendizado da faculdade, adoraria receber &lt;strong&gt;feedbacks e conselhos nos comentários&lt;/strong&gt;! Como foi o seu primeiro contato com Cloud Computing?&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>cloud</category>
      <category>portuguese</category>
      <category>learning</category>
    </item>
    <item>
      <title>IND-TECH WEEKLY #3: Pixxel's $100M Rocket Ride, Jio's Investor Roadshow Kicks Off, and Oracle's Next Layoff Wave 🇮🇳</title>
      <dc:creator>Dhruv Jani</dc:creator>
      <pubDate>Sun, 13 Sep 2026 02:57:39 +0000</pubDate>
      <link>https://dev.to/dj29/ind-tech-weekly-3-pixxels-100m-rocket-ride-jios-investor-roadshow-kicks-off-and-oracles-1b9o</link>
      <guid>https://dev.to/dj29/ind-tech-weekly-3-pixxels-100m-rocket-ride-jios-investor-roadshow-kicks-off-and-oracles-1b9o</guid>
      <description>&lt;p&gt;Hey 👋&lt;/p&gt;

&lt;p&gt;Last issue introduced Jobs Watch, and it's sticking around — this issue keeps that structure and adds one change to Developer Corner (more on that below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This issue covers India tech news from Sunday, Sep 6 to Saturday, Sep 12.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Inside
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📰 The Big Headline — Pixxel's $100M Rocket Ride&lt;/li&gt;
&lt;li&gt;💰 This Week in Funding&lt;/li&gt;
&lt;li&gt;📌 Quick Hits, Worth Knowing&lt;/li&gt;
&lt;li&gt;🌐 The Bigger AI Picture&lt;/li&gt;
&lt;li&gt;💼 Jobs Watch — Stats, Layoffs, and Who's Hiring&lt;/li&gt;
&lt;li&gt;💻 Developer Corner&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - 🗳️ What Do You Want in Issue #4?
&lt;/h2&gt;

&lt;h2&gt;
  
  
  📰 The Big Headline — Pixxel's $100M Rocket Ride
&lt;/h2&gt;

&lt;p&gt;Bengaluru-based space-tech company Pixxel closed a &lt;strong&gt;$100 million Series C&lt;/strong&gt; on September 7 — co-led by Temasek and Seraphim Space, with new investors 360 ONE Asset and South Korea's IMM Investment joining existing backers Radical Ventures and growX Ventures (&lt;a href="https://beststartup.in/india-startup-funding-september-2026-week-one/" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;A few things worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This takes Pixxel's total funding to $195 million, making it the best-capitalised private space-tech company in India's history.&lt;/li&gt;
&lt;li&gt;Founded in 2019 by Awais Ahmed and Kshitij Khandelwal, Pixxel builds hyperspectral satellites that capture far more detail about Earth's surface than conventional optical imaging.&lt;/li&gt;
&lt;li&gt;The round is being read as a signal that Indian deep-tech — not just fintech and consumer apps — can now pull in serious late-stage capital.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Jio update, since we've been tracking it:&lt;/strong&gt; investor outreach for Jio Platforms' IPO is starting this week, with roadshows planned across the US, Singapore, Hong Kong, London and the Middle East. Reports now peg the target valuation at around &lt;strong&gt;$137 billion&lt;/strong&gt;, with the Navratri window (announced last issue) still the plan (&lt;a href="https://www.freepressjournal.in/business/jio-platforms-steps-up-ipo-preparations-investor-outreach-to-start-later-this-week" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters for devs:&lt;/strong&gt; Pixxel's round is a good data point if you're weighing a deep-tech/hardware path over the usual SaaS-or-fintech default — the capital is clearly there for it now.&lt;/p&gt;




&lt;h2&gt;
  
  
  💰 This Week in Funding
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Startup&lt;/th&gt;
&lt;th&gt;Raise&lt;/th&gt;
&lt;th&gt;What's Notable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://beststartup.in/india-startup-funding-september-2026-week-one/" rel="noopener noreferrer"&gt;Pixxel&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;$100M (Series C)&lt;/td&gt;
&lt;td&gt;Co-led by Temasek and Seraphim Space; India's largest-ever space-tech round; total funding now $195M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://inc42.com/?p=571768" rel="noopener noreferrer"&gt;QNu Labs&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;₹200 Cr (~$21M, Series A1)&lt;/td&gt;
&lt;td&gt;Led by India's National Quantum Mission and Speciale Invest; takes the Bengaluru quantum-cybersecurity company's total raised to ₹375 Cr&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Tracker check, continuing from last issue:&lt;/strong&gt; the gap between trackers was much smaller this week than the ~$127M gap we flagged in Issue #2.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tracker&lt;/th&gt;
&lt;th&gt;Window&lt;/th&gt;
&lt;th&gt;Total Raised&lt;/th&gt;
&lt;th&gt;Deals&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://entrackr.com/report/weekly-funding-report-weekly-funding-report/funding-and-acquisitions-in-indian-startups-this-week-sep-07-sep-12-12523070" rel="noopener noreferrer"&gt;Entrackr&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sep 7 – Sep 12&lt;/td&gt;
&lt;td&gt;$356.8M&lt;/td&gt;
&lt;td&gt;~21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://inc42.com/buzz/from-pixxel-to-swish-indian-startups-raised-over-321-9-mn-this-week/" rel="noopener noreferrer"&gt;Inc42&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sep 7 – Sep 11&lt;/td&gt;
&lt;td&gt;$321.9M&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;
  Why do Entrackr and Inc42 never quite agree?
  &lt;br&gt;
Neither tracker is wrong — they just draw the week's boundary differently and classify deals differently. Entrackr's window this week ran Sep 7–12 (six days); Inc42's ran Sep 7–11 (five days), so Entrackr had one more day to catch late-reported deals. On top of that, "verified" vs "reported" rounds, and what counts as a growth-stage deal versus early-stage, differ slightly between the two. Neither is doing anything wrong — it just means a single "$X raised this week" number is always somebody's specific methodology, not a neutral fact.&lt;br&gt;


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


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
&lt;strong&gt;💡 Takeaway:&lt;/strong&gt; ~$35M apart this time, mostly explained by Entrackr's window running one extra day. Compare that to last week's ~$127M gap — the size of the discrepancy isn't constant, which is itself a useful reminder not to treat any single "$X this week" headline as precise.&lt;br&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  📌 Quick Hits, Worth Knowing
&lt;/h2&gt;

&lt;p&gt;A few smaller things from the same week that didn't need a full section but are worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PB Pay is live.&lt;/strong&gt; PB Fintech's payment aggregator platform has launched operations, open for merchant sign-ups under the RBI license it received in February 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mahindra Finance × Sarvam AI, deeper this time.&lt;/strong&gt; Their voice-AI partnership now spans sales, collections, and employee engagement — voice agents built on Sarvam's platform operate across 12 Indian languages and have handled over 1 crore customer calls so far.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Xflow × HSBC, announced at Global Fintech Fest 2026.&lt;/strong&gt; The partnership lets global businesses collect payments from Indian customers via cards, net banking, and UPI, without needing to set up a local entity in India.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(All three via &lt;a href="https://entrackr.com/report/weekly-funding-report-weekly-funding-report/funding-and-acquisitions-in-indian-startups-this-week-sep-07-sep-12-12523070" rel="noopener noreferrer"&gt;Entrackr's weekly report&lt;/a&gt;.)&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 The Bigger AI Picture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SEMICON India 2026 is now just days away&lt;/strong&gt; — September 17–19 in New Delhi, themed "Silicon to Systems." We flagged this last issue as one to watch; it's arriving right after this issue goes out.&lt;/p&gt;

&lt;p&gt;Also worth connecting here: QNu Labs' raise above isn't just a funding story — it's tied to India's &lt;strong&gt;National Quantum Mission&lt;/strong&gt;, which has set a target of quantum resilience across critical infrastructure by 2029. Part of QNu's new capital is earmarked for a government-backed project to build the technology backbone of India's Quantum Secure and Sensing Networks (&lt;a href="https://yourstory.com/2026/09/qnu-labs-raises-rs-200-cr-as-demand-for-quantum-safe-cybersecurity-grows" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it matters for devs:&lt;/strong&gt; semiconductors, quantum, and AI infra are increasingly being funded and framed as one connected pipeline rather than separate policy tracks. If you're picking a deep-tech niche, that's worth factoring in.&lt;/p&gt;




&lt;h2&gt;
  
  
  💼 Jobs Watch — Stats, Layoffs, and Who's Hiring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Big Picture
&lt;/h3&gt;

&lt;p&gt;Naukri's JobSpeak report for August 2026 (published Sep 9) showed white-collar hiring up &lt;strong&gt;14% YoY&lt;/strong&gt;, with the index at 3,028 versus 2,664 a year earlier. Fresher hiring (0–3 years) grew &lt;strong&gt;15% YoY&lt;/strong&gt;, and AI-ML roles led all categories at &lt;strong&gt;31% YoY&lt;/strong&gt; growth. IT hiring specifically grew 11% (&lt;a href="https://www.businesstoday.in/jobs/story/looking-for-your-next-job-these-sectors-are-driving-indias-14-hiring-growth-check-the-full-list-here-554254-2026-09-09" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;One honest caveat in the same report: the index was actually down ~6% &lt;em&gt;month-on-month&lt;/em&gt; from July, because the festive hiring bump shifted later in the calendar this year. So "14% up" and "6% down" are both true at once, depending on whether you're comparing to last year or last month.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layoffs This Week
&lt;/h3&gt;

&lt;p&gt;The macro picture: more than &lt;strong&gt;6,300 tech jobs were cut globally in just the first 10 days of September&lt;/strong&gt;, with Uber, PayPal, Apple, Zomato, and Oracle all named. Layoffs.fyi puts the global 2026 total at &lt;strong&gt;128,536 tech employees across 299 companies&lt;/strong&gt; as of September 10 (&lt;a href="https://www.business-standard.com/industry/news/global-tech-layoffs-2026-oracle-amazon-dell-uber-paypal-it-sector-job-cuts-126091100188_1.html" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The India-specific one to watch: &lt;strong&gt;Oracle India is reportedly bracing for another 2,000–3,000 job cuts&lt;/strong&gt;, expected around September 15 — just after this issue's window closes. This would follow an earlier 2026 round that already affected roughly 12,000 Oracle employees in India (&lt;a href="https://www.freepressjournal.in/tech/oracle-to-face-fresh-round-of-layoffs-this-month-thousands-of-indian-employees-to-be-affected" rel="noopener noreferrer"&gt;source&lt;/a&gt;). Oracle hasn't officially confirmed a date.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
&lt;strong&gt;💡 Takeaway:&lt;/strong&gt; the same industry capex boom driving AI infrastructure spending (Alphabet, Amazon, Microsoft, and Meta are expected to spend ~$725 billion on capex in 2026, up 77% from 2025) is part of the reason companies are simultaneously cutting headcount elsewhere. Growing revenue and shrinking teams aren't contradictory anymore.&lt;br&gt;

&lt;/div&gt;


&lt;h3&gt;
  
  
  Who's Actually Hiring
&lt;/h3&gt;

&lt;p&gt;Zooming into the Naukri numbers above: auto (+19% YoY), healthcare (+16%), and retail (+15%) led sector hiring growth in August — not IT. If you're a fresher and only tracking tech-sector headlines, it's worth knowing that some of the strongest hiring momentum right now is happening outside pure-play tech companies altogether.&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Developer Corner
&lt;/h2&gt;

&lt;p&gt;Starting this issue, Developer Corner is changing format. Instead of me sourcing opportunities myself each week, I asked &lt;a class="mentioned-user" href="https://dev.to/hemapriya_kanagala"&gt;@hemapriya_kanagala&lt;/a&gt;, who runs the excellent &lt;strong&gt;Dev Opportunity Radar&lt;/strong&gt; series, whether I could just point readers to her weekly post. She said yes — so going forward, every issue of IND-TECH WEEKLY will carry a Liquid tag to that week's Radar edition here.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/devengers/dev-opportunity-radar-16-15k-ai-agent-hackathon-ai-education-fellowship-and-aws-student-rewards-4l2e" class="crayons-story__hidden-navigation-link"&gt;Dev Opportunity Radar #16: $15K AI Agent Hackathon, AI Education Fellowship, and AWS Student Rewards&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/devengers/dev-opportunity-radar-16-15k-ai-agent-hackathon-ai-education-fellowship-and-aws-student-rewards-4l2e" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Includes reader-submitted hacks and site updates&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/devengers"&gt;
            &lt;img alt="The DEVengers logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F12483%2Fb3a03d2d-fbb6-4355-9593-dff0f92638e9.webp" class="crayons-logo__image" width="800" height="800"&gt;
          &lt;/a&gt;

          &lt;a href="/hemapriya_kanagala" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3307586%2F2dffaf97-946d-44a6-8a39-07d94a72e07d.png" alt="hemapriya_kanagala profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/hemapriya_kanagala" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Hemapriya Kanagala
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Hemapriya Kanagala
                
                
              
              &lt;div id="story-author-preview-content-4632958" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/hemapriya_kanagala" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3307586%2F2dffaf97-946d-44a6-8a39-07d94a72e07d.png" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Hemapriya Kanagala&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/devengers" class="crayons-story__secondary fw-medium"&gt;The DEVengers&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/devengers/dev-opportunity-radar-16-15k-ai-agent-hackathon-ai-education-fellowship-and-aws-student-rewards-4l2e" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 11&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/devengers/dev-opportunity-radar-16-15k-ai-agent-hackathon-ai-education-fellowship-and-aws-student-rewards-4l2e" id="article-link-4632958"&gt;
          Dev Opportunity Radar #16: $15K AI Agent Hackathon, AI Education Fellowship, and AWS Student Rewards
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/community"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;community&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opportunities"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opportunities&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/resources"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;resources&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/devengers/dev-opportunity-radar-16-15k-ai-agent-hackathon-ai-education-fellowship-and-aws-student-rewards-4l2e" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;75&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;span class="crayons-story__favorited"&gt;
              &lt;span class="favorited-marker"&gt;
                &lt;span&gt;
                  

                &lt;/span&gt;
                &lt;span class="hidden"&gt;
                  

                &lt;/span&gt;
              &lt;/span&gt;
            &lt;/span&gt;
            &lt;a href="https://dev.to/devengers/dev-opportunity-radar-16-15k-ai-agent-hackathon-ai-education-fellowship-and-aws-student-rewards-4l2e#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              15&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://devopportunityradar.ai.studio/" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;🔍 Browse every past Radar edition&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;If you're after hackathons, fellowships, and other opportunities worth applying to, that's the one to check every week now.&lt;/p&gt;




&lt;h2&gt;
  
  
  🗳️ What Do You Want in Issue #4?
&lt;/h2&gt;

&lt;p&gt;A couple of questions:&lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;The tracker-discrepancy callout in Funding&lt;/strong&gt; — useful as a recurring bit, or was once enough to make the point?&lt;/p&gt;

&lt;p&gt;2️⃣ Anything you want more depth on — the Jio IPO as it gets closer, more on the layoffs wave, or something else entirely?&lt;/p&gt;

&lt;p&gt;Thanks for reading, and see you next Sunday.&lt;/p&gt;




&lt;p&gt;And in case you missed it — &lt;strong&gt;#4&lt;/strong&gt; for &lt;strong&gt;The DEV Guide I Wish Existed&lt;/strong&gt; is &lt;strong&gt;LIVE&lt;/strong&gt;. Check it out below if you haven't already:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/dj29/the-internship-that-taught-me-to-read-between-the-lines-of-a-job-offer-50ef" class="crayons-story__hidden-navigation-link"&gt;The Internship That Taught Me to Read Between the Lines of a Job Offer&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/dj29/the-internship-that-taught-me-to-read-between-the-lines-of-a-job-offer-50ef" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Features a pre-application vetting framework&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/dj29" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3743406%2F227d53d3-1443-4ceb-9fb8-98c02ff9e60f.jpg" alt="dj29 profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/dj29" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Dhruv Jani
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Dhruv Jani
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-4625445" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/dj29" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3743406%2F227d53d3-1443-4ceb-9fb8-98c02ff9e60f.jpg" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Dhruv Jani&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/dj29/the-internship-that-taught-me-to-read-between-the-lines-of-a-job-offer-50ef" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 10&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/dj29/the-internship-that-taught-me-to-read-between-the-lines-of-a-job-offer-50ef" id="article-link-4625445"&gt;
          The Internship That Taught Me to Read Between the Lines of a Job Offer
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devjournal"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devjournal&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/dj29/the-internship-that-taught-me-to-read-between-the-lines-of-a-job-offer-50ef" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;33&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/dj29/the-internship-that-taught-me-to-read-between-the-lines-of-a-job-offer-50ef#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              31&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;🇮🇳 Follow for the next drop — Indian tech doesn't slow down.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__3743406"&gt;
    &lt;a href="/dj29" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3743406%2F227d53d3-1443-4ceb-9fb8-98c02ff9e60f.jpg" alt="dj29 image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/dj29"&gt;Dhruv Jani&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/dj29"&gt;Upcoming Trainee Engineer @ Simform 🚀
Building, experimenting, and writing my way through tech.
AI • Web • Open Source • Challenges
If I find something interesting, I'll probably write about it. 😄&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>india</category>
      <category>news</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Why Type Safety Matters More as a Codebase Grows</title>
      <dc:creator>khg5293</dc:creator>
      <pubDate>Sun, 13 Sep 2026 02:54:50 +0000</pubDate>
      <link>https://dev.to/khg5293/why-type-safety-matters-more-as-a-codebase-grows-14pc</link>
      <guid>https://dev.to/khg5293/why-type-safety-matters-more-as-a-codebase-grows-14pc</guid>
      <description>&lt;p&gt;When a project is small, type safety can feel like extra work.&lt;/p&gt;

&lt;p&gt;If you only have a few files and you wrote most of the code yourself, it is often easy to remember what each function expects and what each object contains.&lt;/p&gt;

&lt;p&gt;That changes quickly as a project grows.&lt;/p&gt;

&lt;p&gt;More components, more API responses, more shared utilities, and more contributors all create opportunities for assumptions to drift.&lt;/p&gt;

&lt;p&gt;One of the biggest benefits of static typing is that it turns many of those assumptions into something the compiler can check.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&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="kr"&gt;number&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;isActive&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="kd"&gt;const&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;User&lt;/span&gt; &lt;span class="o"&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="mi"&gt;5293&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khg5293&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isActive&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a function that expects a User has a clear contract.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;displayUser&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;User&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;displayUser&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the structure changes later, TypeScript can point out the places that need to be updated.&lt;/p&gt;

&lt;p&gt;This becomes especially useful during refactoring.&lt;/p&gt;

&lt;p&gt;Without type checking, changing a shared object or function signature can create bugs in parts of the application that may not be immediately obvious.&lt;/p&gt;

&lt;p&gt;With TypeScript, many of those problems become compile-time errors instead.&lt;/p&gt;

&lt;p&gt;Type safety does not eliminate bugs, and it does not replace testing.&lt;/p&gt;

&lt;p&gt;But as a codebase becomes larger, it reduces the amount of information developers have to keep in their heads.&lt;/p&gt;

&lt;p&gt;That is where I think TypeScript becomes most valuable.&lt;/p&gt;

&lt;p&gt;It is not just about preventing simple mistakes.&lt;/p&gt;

&lt;p&gt;It is about making larger systems easier to change with confidence.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why Parameterized Queries Matter for SQL Security</title>
      <dc:creator>khg5293</dc:creator>
      <pubDate>Sun, 13 Sep 2026 02:52:44 +0000</pubDate>
      <link>https://dev.to/khg5293/why-parameterized-queries-matter-for-sql-security-1iem</link>
      <guid>https://dev.to/khg5293/why-parameterized-queries-matter-for-sql-security-1iem</guid>
      <description>&lt;p&gt;SQL injection is one of the classic examples of what can happen when an application mixes user input directly into a database query.&lt;/p&gt;

&lt;p&gt;The underlying problem is simple.&lt;/p&gt;

&lt;p&gt;The application expects data.&lt;/p&gt;

&lt;p&gt;The database may interpret part of that data as SQL code.&lt;/p&gt;

&lt;p&gt;That is why parameterized queries are such an important security control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The unsafe approach
&lt;/h2&gt;

&lt;p&gt;Imagine a simple project lookup page where a user submits a project name.&lt;/p&gt;

&lt;p&gt;An unsafe query might be built like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectName&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;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM projects WHERE name = '&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="nx"&gt;projectName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;"&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="nf"&gt;query&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the input is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;khg5293-json-formatter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the final query becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;projects&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'khg5293-json-formatter'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That looks fine.&lt;/p&gt;

&lt;p&gt;The problem is that the application is directly combining input with SQL syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this becomes dangerous
&lt;/h2&gt;

&lt;p&gt;An attacker is not required to submit the value the application expects.&lt;/p&gt;

&lt;p&gt;They may provide input containing characters that change the meaning of the query.&lt;/p&gt;

&lt;p&gt;Once user input becomes part of the SQL statement itself, the database may interpret it as executable SQL instead of ordinary data.&lt;/p&gt;

&lt;p&gt;That is the security boundary we want to preserve.&lt;/p&gt;

&lt;p&gt;The application should control the SQL structure.&lt;/p&gt;

&lt;p&gt;The user should only control the values being supplied to that structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parameterized queries separate code from data
&lt;/h2&gt;

&lt;p&gt;A safer version looks like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectName&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="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM projects WHERE name = ?&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;projectName&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;Here, the SQL statement and the user supplied value are passed separately.&lt;/p&gt;

&lt;p&gt;The database driver handles the parameter as data rather than inserting it directly into the SQL syntax.&lt;/p&gt;

&lt;p&gt;This is much easier to reason about and significantly safer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Another example
&lt;/h2&gt;

&lt;p&gt;Imagine a page that retrieves a project using a numeric ID.&lt;/p&gt;

&lt;p&gt;A parameterized query could look like this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;projectId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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="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="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
  &lt;span class="nx"&gt;projectId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid project ID&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;db&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM projects WHERE id = ?&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;projectId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This combines two useful controls.&lt;/p&gt;

&lt;p&gt;First, the server validates that &lt;code&gt;projectId&lt;/code&gt; is actually a positive integer.&lt;/p&gt;

&lt;p&gt;Second, the value is passed into the SQL query as a parameter.&lt;/p&gt;

&lt;p&gt;Validation and parameterization solve different problems, but they work well together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input validation alone is not enough
&lt;/h2&gt;

&lt;p&gt;It is tempting to think that filtering suspicious characters is enough to prevent SQL injection.&lt;/p&gt;

&lt;p&gt;For example:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a good primary defense.&lt;/p&gt;

&lt;p&gt;Attack techniques can vary, database syntax can vary, and maintaining a list of every dangerous pattern is difficult.&lt;/p&gt;

&lt;p&gt;The safer approach is to design the query so that user input is never interpreted as SQL syntax in the first place.&lt;/p&gt;

&lt;p&gt;That is exactly what parameterized queries are designed to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid building queries manually
&lt;/h2&gt;

&lt;p&gt;Consider this:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&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;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM projects WHERE owner = '&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;' AND status = '&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;"&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="nf"&gt;query&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The more values that are concatenated into a query, the harder the code becomes to reason about safely.&lt;/p&gt;

&lt;p&gt;A parameterized version is much cleaner:&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="nx"&gt;db&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM projects WHERE owner = ? AND status = ?&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;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&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;The SQL structure stays fixed.&lt;/p&gt;

&lt;p&gt;Only the values change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parameterized queries also improve readability
&lt;/h2&gt;

&lt;p&gt;Security is the main benefit, but parameterized queries usually make code easier to read as well.&lt;/p&gt;

&lt;p&gt;For example:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khg5293&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TypeScript&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&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="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT INTO projects (owner, language, status) VALUES (?, ?, ?)&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;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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;It is immediately clear which values are being inserted and where they belong.&lt;/p&gt;

&lt;p&gt;The developer does not have to manually worry about quoting or concatenating each value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parameterization is not the entire security model
&lt;/h2&gt;

&lt;p&gt;Parameterized queries are extremely important, but they are still only one layer.&lt;/p&gt;

&lt;p&gt;Applications should also consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input validation&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;Least privilege database accounts&lt;/li&gt;
&lt;li&gt;Secure error handling&lt;/li&gt;
&lt;li&gt;Logging and monitoring&lt;/li&gt;
&lt;li&gt;Rate limiting where appropriate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a perfectly parameterized query is still a problem if any user can access data they are not authorized to see.&lt;/p&gt;

&lt;p&gt;Security controls solve different parts of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful mental model
&lt;/h2&gt;

&lt;p&gt;I like to think of it this way:&lt;/p&gt;

&lt;p&gt;SQL belongs to the application.&lt;/p&gt;

&lt;p&gt;Data belongs to the user.&lt;/p&gt;

&lt;p&gt;The application should never let user supplied data become part of the SQL language itself.&lt;/p&gt;

&lt;p&gt;For example:&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="nx"&gt;db&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM projects WHERE owner = ?&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;khg5293&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fundamentally safer than constructing the SQL statement by combining strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Parameterized queries are not complicated, but they solve an important problem.&lt;/p&gt;

&lt;p&gt;They create a clear separation between SQL instructions and user supplied data.&lt;/p&gt;

&lt;p&gt;Input validation is still valuable.&lt;/p&gt;

&lt;p&gt;Authorization is still necessary.&lt;/p&gt;

&lt;p&gt;Other defensive layers still matter.&lt;/p&gt;

&lt;p&gt;But when an application interacts with a SQL database, parameterization should be the default way to handle values.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
