<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[SHIFT ASIA | Dev Blog]]></title><description><![CDATA[Software QA and Development Professionals]]></description><link>https://shiftasia.com/community/</link><image><url>https://shiftasia.com/community/favicon.png</url><title>SHIFT ASIA | Dev Blog</title><link>https://shiftasia.com/community/</link></image><generator>Ghost 4.8</generator><lastBuildDate>Mon, 06 Apr 2026 09:51:34 GMT</lastBuildDate><atom:link href="https://shiftasia.com/community/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Pages and Blocks in SQL Databases]]></title><description><![CDATA[A page is the smallest unit of data that a database system reads from or writes to disk, and the smallest unit of memory allocation.]]></description><link>https://shiftasia.com/community/pages-and-blocks-in-sql-databases/</link><guid isPermaLink="false">6931c28418cce10001f0d0a5</guid><category><![CDATA[Database]]></category><dc:creator><![CDATA[King]]></dc:creator><pubDate>Sat, 13 Dec 2025 04:40:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/download.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://shiftasia.com/community/content/images/2025/12/download.jpg" alt="Pages and Blocks in SQL Databases"><p>The Hidden Foundation That Powers Every Query You Run</p>
<p>When you write <code>SELECT * FROM Users WHERE Id = 42</code>, you probably think about tables, rows, and indexes.</p>
<p>But long before your row reaches the execution engine, the database engine has already performed a crucial step: it read one or more 8 KB (or 16 KB) chunks from disk called pages (or blocks).</p>
<p>These pages are the real physical building blocks of every major relational database. Understanding them is the difference between guessing why a query is slow and knowing exactly why.</p>
<h3 id="what-exactly-is-a-page-or-block">What Exactly Is a Page (or Block)?</h3>
<p>A page is the smallest unit of data that a database reads from or writes to disk in a single I/O operation.</p>
<p>Think of it like this:</p>
<ul>
<li>You ask for one sentence from a book.</li>
<li>The librarian doesn&#x2019;t hand you just that sentence.</li>
<li>She hands you the entire page the sentence lives on.</li>
</ul>
<p>That&#x2019;s exactly how databases work.</p>
<p><img src="https://shiftasia.com/community/content/images/2025/12/Screenshot-2025-12-11-113027.png" alt="Pages and Blocks in SQL Databases" loading="lazy"></p>
<h3 id="anatomy-of-a-typical-data-page-sql-server-example">Anatomy of a Typical Data Page (SQL Server Example)</h3>
<p>An 8 KB SQL Server data page looks like this in memory/disk:</p>
<pre><code>+--------------------------------------------------+
| Page Header                  96 bytes           |
+--------------------------------------------------+
| Data Rows                    variable           |
| (actual table records)                           |
+--------------------------------------------------+
| Free Space                   variable           |
+--------------------------------------------------+
| Row Offset Array             2&#x2013;4 bytes per row  |
| (pointers to start of each row, at end of page) |
+--------------------------------------------------+
Total = exactly 8192 bytes

</code></pre>
<p>The 96-byte header contains:</p>
<ul>
<li>Page number (Page PID)</li>
<li>Previous/next page pointers (for heap or clustered index)</li>
<li>Page type (data, index, LOB, IAM, etc.)</li>
<li>Free space available</li>
<li>Checksum (if enabled)</li>
<li>LSN (Log Sequence Number)</li>
</ul>
<h3 id="different-types-of-pages">Different Types of Pages</h3>
<p>Not all pages store regular table rows.</p>
<p><img src="https://shiftasia.com/community/content/images/2025/12/Screenshot-2025-12-11-112908.png" alt="Pages and Blocks in SQL Databases" loading="lazy"></p>
<h3 id="why-page-size-directly-affects-your-database-design">Why Page Size Directly Affects Your Database Design</h3>
<ol>
<li>
<p>Maximum Row Size</p>
<p>SQL Server: ~8,060 bytes per row</p>
<p>&#x2192; Because a row must fit on a single data page (minus header and offset array).</p>
<p>&#x2192; Anything larger &#x2192; automatically moved to LOB/row-overflow pages.</p>
</li>
<li>
<p>Wide Tables Force More Pages &#x2192; More I/O</p>
<p>A table with 10-byte rows can store ~800 rows per page.</p>
<p>A table with 7,000-byte rows stores only 1 row per page &#x2192; 800&#xD7; more I/O.</p>
</li>
<li>
<p>Index Depth</p>
<p>Smaller page size = more levels in B-tree = slower seeks.</p>
<p>That&#x2019;s one reason MySQL InnoDB moved from 8 KB &#x2192; 16 KB default.</p>
</li>
</ol>
<h3 id="the-dreaded-page-split">The Dreaded Page Split</h3>
<p>Imagine a page that is 98% full. You insert or update a row that no longer fits.</p>
<p>What happens?</p>
<ol>
<li>Database allocates a brand-new page.</li>
<li>Roughly half the rows move to the new page.</li>
<li>Both pages are now ~50% full.</li>
<li>Physical order on disk may now be fragmented.</li>
</ol>
<p>Result:</p>
<ul>
<li>Wasted space (internal fragmentation)</li>
<li>Slower range scans (external fragmentation)</li>
<li>Heavy write amplification</li>
</ul>
<p>This is why DBAs obsess over fillfactor and rebuild/reorganize indexes.</p>
<h3 id="real-world-performance-examples">Real-World Performance Examples</h3>
<p><img src="https://shiftasia.com/community/content/images/2025/12/Screenshot-2025-12-11-112756.png" alt="Pages and Blocks in SQL Databases" loading="lazy"></p>
<h3 id="how-to-see-pages-in-action">How to See Pages in Action</h3>
<p>SQL Server</p>
<pre><code class="language-sql">-- See what is actually on a page (undocumented but safe)
DBCC TRACEON(3604);                    -- redirect output to SSMS
DBCC PAGE (&apos;YourDatabase&apos;, 1, 12345, 3); -- file 1, page 12345, style 3

</code></pre>
<p>PostgreSQL</p>
<pre><code class="language-sql">-- Install and use pageinspect extension
CREATE EXTENSION pageinspect;
SELECT * FROM page_header(get_raw_page(&apos;users&apos;, 0));

</code></pre>
<p>Oracle</p>
<pre><code class="language-sql">-- Dump a block
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 42;

</code></pre>
<p>MySQL InnoDB</p>
<pre><code class="language-sql">-- Use innodb_ruby or Percona&#x2019;s tools
innodb_space -f data/ibdata1 page-dump 100

</code></pre>
<h3 id="best-practice-checklist-based-on-page-knowledge">Best Practice Checklist Based on Page Knowledge</h3>
<p><img src="https://shiftasia.com/community/content/images/2025/12/Screenshot-2025-12-11-112633.png" alt="Pages and Blocks in SQL Databases" loading="lazy"></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Understanding Immutability: Importance, Use Cases, and Implementation in JavaScript]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Immutability is a core concept in programming where an object or data structure cannot be modified after it is created. In contrast, mutable objects can be altered post-creation. Immutability plays a pivotal role in writing robust, predictable, and maintainable code, particularly in modern JavaScript applications. This article explores why immutability</p>]]></description><link>https://shiftasia.com/community/understanding-immutability-importance-use-cases-and-implementation-in-javascript/</link><guid isPermaLink="false">684b854818cce10001f09d5f</guid><category><![CDATA[Javascripts]]></category><dc:creator><![CDATA[King]]></dc:creator><pubDate>Fri, 12 Dec 2025 04:18:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/06/images.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://shiftasia.com/community/content/images/2025/06/images.png" alt="Understanding Immutability: Importance, Use Cases, and Implementation in JavaScript"><p>Immutability is a core concept in programming where an object or data structure cannot be modified after it is created. In contrast, mutable objects can be altered post-creation. Immutability plays a pivotal role in writing robust, predictable, and maintainable code, particularly in modern JavaScript applications. This article explores why immutability is important, when to use immutable versus mutable data, and how to implement immutability in JavaScript with practical examples and relevant libraries.</p>
<h2 id="why-is-immutability-important">Why is Immutability Important?</h2>
<p>Immutability offers several benefits that make it a cornerstone of reliable software design:</p>
<ol>
<li>
<p><strong>Thread Safety and Concurrency</strong>: Immutable objects are inherently thread-safe because their state cannot change. In JavaScript, which is single-threaded but often handles asynchronous operations (e.g., via promises or async/await), immutability prevents unexpected state changes in shared data across asynchronous tasks.</p>
</li>
<li>
<p><strong>Predictability and Debugging</strong>: Immutable data ensures that a value remains consistent throughout its lifecycle. This eliminates side effects, making it easier to reason about code and debug issues. For example, if a function receives an immutable object, you can trust it won&#x2019;t be modified unexpectedly elsewhere.</p>
</li>
<li>
<p><strong>Functional Programming</strong>: Immutability is a key principle in functional programming, enabling pure functions that always produce the same output for the same input. This leads to cleaner, more composable code, as seen in frameworks like React or Redux.</p>
</li>
<li>
<p><strong>Data Integrity</strong>: In applications where data consistency is critical (e.g., financial systems or configuration management), immutability prevents accidental or unauthorized changes.</p>
</li>
<li>
<p><strong>Efficient Caching</strong>: Since immutable objects don&#x2019;t change, they can be safely cached or used as keys in hash-based structures (e.g., JavaScript <code>Map</code> or <code>Set</code>) without worrying about state changes affecting their hash.</p>
</li>
<li>
<p><strong>Simplified State Management</strong>: In front-end development, immutability simplifies state management in libraries like Redux, where state changes are handled by creating new state objects rather than modifying existing ones.</p>
</li>
</ol>
<p>However, immutability comes with trade-offs. Creating new objects for every change can increase memory usage and impact performance in scenarios requiring frequent updates. Understanding when to use immutable versus mutable data is crucial.</p>
<h2 id="when-to-use-immutable-vs-mutable-data">When to Use Immutable vs. Mutable Data</h2>
<h3 id="when-to-use-immutable-data">When to Use Immutable Data</h3>
<ul>
<li><strong>Fixed or Constant Data</strong>: Use immutability for data that shouldn&#x2019;t change, such as configuration settings, user IDs, or API response snapshots.</li>
<li><strong>Concurrent or Asynchronous Code</strong>: Immutability prevents race conditions in asynchronous JavaScript code, such as when handling multiple API calls or event listeners.</li>
<li><strong>Functional Programming</strong>: When writing pure functions or working with libraries like Redux, immutability ensures predictable behavior.</li>
<li><strong>Hash Map Keys</strong>: Immutable objects are ideal as keys in <code>Map</code> or <code>Set</code> because their values (and hash codes) remain constant.</li>
<li><strong>Shared Data</strong>: When passing data between components or modules, immutability prevents unintended modifications.</li>
<li><strong>Critical Systems</strong>: In domains like finance or security, immutability ensures data integrity for records like transactions or audit logs.</li>
</ul>
<h3 id="when-to-use-mutable-data">When to Use Mutable Data</h3>
<ul>
<li><strong>Frequent Updates</strong>: If an object&#x2019;s state changes often, mutability avoids the overhead of creating new objects. For example, updating an array in place is faster than creating a new one.</li>
<li><strong>Performance-Critical Applications</strong>: In scenarios where memory or CPU efficiency is critical (e.g., real-time games), mutable objects reduce overhead.</li>
<li><strong>Modeling Dynamic State</strong>: For objects representing real-world entities that change, like a game character&#x2019;s position or a shopping cart&#x2019;s contents.</li>
<li><strong>Temporary Data</strong>: Mutable objects are suitable for intermediary or scratchpad data during computations, such as sorting an array.</li>
<li><strong>Single-Threaded Contexts</strong>: In JavaScript&#x2019;s single-threaded environment, mutability is often safe for local, non-shared data.</li>
</ul>
<h2 id="immutability-in-javascript">Immutability in JavaScript</h2>
<p>JavaScript does not enforce immutability by default, but it provides tools and patterns to achieve it. Below, we explore how to implement immutability using native JavaScript features and popular libraries, with practical examples.</p>
<h3 id="native-javascript-immutability">Native JavaScript Immutability</h3>
<p>JavaScript offers several ways to enforce or simulate immutability:</p>
<ol>
<li><strong>Object.freeze()</strong>: Prevents modifications to an object&#x2019;s properties.</li>
<li><strong>const</strong>: Prevents reassignment of a variable (though the object&#x2019;s properties can still be mutated).</li>
<li><strong>Spread Operator (<code>...</code>)</strong>: Creates shallow copies of objects or arrays for non-mutating updates.</li>
<li><strong>Array Methods</strong>: Methods like <code>map</code>, <code>filter</code>, and <code>slice</code> return new arrays without modifying the original.</li>
</ol>
<h4 id="example-1-using-objectfreeze">Example 1: Using <code>Object.freeze()</code></h4>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code class="language-javascript">const user = Object.freeze({
  id: 1,
  name: &quot;Alice&quot;,
  address: { city: &quot;New York&quot; }
});

// Attempting to modify the object throws an error in strict mode
user.name = &quot;Bob&quot;; // Fails silently (or throws in strict mode)
console.log(user.name); // &quot;Alice&quot;

// Note: Object.freeze is shallow; nested objects can still be modified
user.address.city = &quot;Boston&quot;; // Works!
console.log(user.address.city); // &quot;Boston&quot;

// For deep immutability, use a deep freeze function
function deepFreeze(obj) {
  Object.getOwnPropertyNames(obj).forEach(name =&gt; {
    const prop = obj[name];
    if (typeof prop === &quot;object&quot; &amp;&amp; prop !== null) {
      deepFreeze(prop);
    }
  });
  return Object.freeze(obj);
}

const deepUser = deepFreeze({ id: 2, name: &quot;Charlie&quot;, address: { city: &quot;Seattle&quot; } });
deepUser.address.city = &quot;Portland&quot;; // Fails silently (or throws in strict mode)
console.log(deepUser.address.city); // &quot;Seattle&quot;
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h4 id="example-2-using-the-spread-operator">Example 2: Using the Spread Operator</h4>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code class="language-javascript">const cart = { items: [&quot;apple&quot;, &quot;banana&quot;], total: 5 };

// Create a new cart with an added item
const updatedCart = {
  ...cart,
  items: [...cart.items, &quot;orange&quot;],
  total: cart.total + 2
};

console.log(cart.items); // [&quot;apple&quot;, &quot;banana&quot;]
console.log(updatedCart.items); // [&quot;apple&quot;, &quot;banana&quot;, &quot;orange&quot;]
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h4 id="example-3-immutable-array-operations">Example 3: Immutable Array Operations</h4>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code class="language-javascript">const numbers = [1, 2, 3, 4];

// Non-mutating: map creates a new array
const doubled = numbers.map(n =&gt; n * 2);
console.log(doubled); // [2, 4, 6, 8]
console.log(numbers); // [1, 2, 3, 4] (original unchanged)

// Mutating: push modifies the original array
numbers.push(5);
console.log(numbers); // [1, 2, 3, 4, 5]
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h3 id="libraries-for-immutability">Libraries for Immutability</h3>
<p>Several JavaScript libraries simplify working with immutable data, offering robust APIs and performance optimizations. Here are the most popular ones:</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>1.<strong>Immutable.js</strong></p>
<ul>
<li><strong>Description</strong>: Developed by Facebook, Immutable.js provides persistent immutable data structures like <code>List</code>, <code>Map</code>, and <code>Set</code>. It optimizes memory usage with structural sharing, where unchanged parts of a data structure are reused.</li>
<li><strong>Use Case</strong>: Ideal for complex state management in applications like React or Redux.</li>
<li><strong>Installation</strong>: <code>npm install immutable</code></li>
<li><strong>Example</strong>:</li>
</ul>
<pre><code class="language-javascript">import { Map, List } from &quot;immutable&quot;;

// Create an immutable map
let user = Map({ id: 1, name: &quot;Alice&quot;, hobbies: List([&quot;reading&quot;, &quot;gaming&quot;]) });

// Update immutably
let updatedUser = user.set(&quot;name&quot;, &quot;Bob&quot;).update(&quot;hobbies&quot;, hobbies =&gt; hobbies.push(&quot;coding&quot;));

console.log(user.get(&quot;name&quot;)); // &quot;Alice&quot;
console.log(updatedUser.get(&quot;name&quot;)); // &quot;Bob&quot;
console.log(updatedUser.get(&quot;hobbies&quot;).toArray()); // [&quot;reading&quot;, &quot;gaming&quot;, &quot;coding&quot;]
</code></pre>
<p>2.<strong>Immer</strong></p>
<ul>
<li><strong>Description</strong>: Immer simplifies immutability by allowing you to write &#x201C;mutative&#x201D; code that produces immutable results. It uses a draft state that you can modify, and Immer creates a new immutable object behind the scenes.</li>
<li><strong>Use Case</strong>: Great for Redux or React state updates where you want readable, mutative-style code without manual copying.</li>
<li><strong>Installation</strong>: <code>npm install immer</code></li>
<li><strong>Example</strong>:</li>
</ul>
<pre><code class="language-javascript"> import produce from &quot;immer&quot;;

 const state = { user: { name: &quot;Alice&quot;, age: 30 }, items: [&quot;apple&quot;] };

 const newState = produce(state, draft =&gt; {
   draft.user.name = &quot;Bob&quot;; // Mutate draft safely
   draft.items.push(&quot;banana&quot;);
 });

 console.log(state.user.name); // &quot;Alice&quot; (original unchanged)
 console.log(newState.user.name); // &quot;Bob&quot;
 console.log(newState.items); // [&quot;apple&quot;, &quot;banana&quot;]
</code></pre>
<p>3.<strong>Seamless-Immutable</strong></p>
<ul>
<li><strong>Description</strong>: A lightweight library that provides immutable data structures with a simple API. It wraps native JavaScript objects and arrays to prevent mutations.</li>
<li><strong>Use Case</strong>: Suitable for projects needing lightweight immutability without the complexity of Immutable.js.</li>
<li><strong>Installation</strong>: <code>npm install seamless-immutable</code></li>
<li><strong>Example</strong>:</li>
</ul>
<pre><code class="language-javascript">import SeamlessImmutable from &quot;seamless-immutable&quot;;

const state = SeamlessImmutable({ user: { name: &quot;Alice&quot; }, items: [&quot;apple&quot;] });

// Update immutably
const newState = state.merge({ user: { name: &quot;Bob&quot; }, items: [...state.items, &quot;banana&quot;] });

console.log(state.user.name); // &quot;Alice&quot;
console.log(newState.user.name); // &quot;Bob&quot;
console.log(newState.items); // [&quot;apple&quot;, &quot;banana&quot;]
</code></pre>
<p>4.<strong>Mori</strong></p>
<ul>
<li><strong>Description</strong>: A library that brings Clojure&#x2019;s persistent data structures to JavaScript. It&#x2019;s similar to Immutable.js but with a functional programming focus.</li>
<li><strong>Use Case</strong>: Best for functional programming enthusiasts or projects requiring Clojure-style data structures.</li>
<li><strong>Installation</strong>: <code>npm install mori</code></li>
<li><strong>Example</strong>:</li>
</ul>
<pre><code class="language-javascript">import mori from &quot;mori&quot;;

let state = mori.hashMap(&quot;user&quot;, mori.hashMap(&quot;name&quot;, &quot;Alice&quot;), &quot;items&quot;, mori.vector(&quot;apple&quot;));

let newState = mori.assoc(state, &quot;user&quot;, mori.assoc(mori.get(state, &quot;user&quot;), &quot;name&quot;, &quot;Bob&quot;));
newState = mori.assoc(newState, &quot;items&quot;, mori.conj(mori.get(newState, &quot;items&quot;), &quot;banana&quot;));

console.log(mori.get(state, &quot;user&quot;).get(&quot;name&quot;)); // &quot;Alice&quot;
console.log(mori.get(newState, &quot;user&quot;).get(&quot;name&quot;)); // &quot;Bob&quot;
console.log(mori.toJs(mori.get(newState, &quot;items&quot;))); // [&quot;apple&quot;, &quot;banana&quot;]
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="practical-example-redux-with-immutability">Practical Example: Redux with Immutability</h2>
<p>Redux, a popular state management library for React, enforces immutability for predictable state updates. Here&#x2019;s an example of a Redux reducer using Immer for immutability:</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code class="language-javascript">import produce from &quot;immer&quot;;

// Initial state
const initialState = {
  todos: [
    { id: 1, text: &quot;Learn JavaScript&quot;, completed: false }
  ]
};

// Reducer with Immer
const todoReducer = produce((draft, action) =&gt; {
  switch (action.type) {
    case &quot;ADD_TODO&quot;:
      draft.todos.push({ id: action.id, text: action.text, completed: false });
      break;
    case &quot;TOGGLE_TODO&quot;:
      const todo = draft.todos.find(t =&gt; t.id === action.id);
      if (todo) todo.completed = !todo.completed;
      break;
  }
}, initialState);

// Example usage
const state1 = todoReducer(initialState, { type: &quot;ADD_TODO&quot;, id: 2, text: &quot;Learn Immutability&quot; });
console.log(state1.todos); // [{ id: 1, ... }, { id: 2, text: &quot;Learn Immutability&quot;, completed: false }]
console.log(initialState.todos); // [{ id: 1, ... }] (original unchanged)

const state2 = todoReducer(state1, { type: &quot;TOGGLE_TODO&quot;, id: 1 });
console.log(state2.todos[0].completed); // true
</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="trade-offs-and-best-practices">Trade-offs and Best Practices</h2>
<ul>
<li><strong>Performance</strong>: Immutability can increase memory usage due to creating new objects. Libraries like Immutable.js and Immer use structural sharing to mitigate this, but for performance-critical applications, profile memory usage carefully.</li>
<li><strong>Learning Curve</strong>: Libraries like Immutable.js or Mori have a steeper learning curve due to their unique APIs. Immer is more beginner-friendly as it allows mutative-style code.</li>
<li><strong>Shallow vs. Deep Immutability</strong>: Native <code>Object.freeze()</code> is shallow, so nested objects can still be mutated. Use deep-freezing functions or libraries for full immutability.</li>
<li><strong>Choose the Right Tool</strong>: Use native JavaScript (spread operator, <code>Object.freeze</code>) for simple cases. For complex state management, consider Immer or Immutable.js.</li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="conclusion">Conclusion</h2>
<p>Immutability is a powerful concept that enhances code reliability, predictability, and safety, particularly in asynchronous JavaScript applications, functional programming, and state management. By using native features like <code>Object.freeze</code> and the spread operator, or libraries like Immutable.js, Immer, Seamless-Immutable, or Mori, developers can enforce immutability effectively. Choose immutability for fixed data, concurrent systems, or critical applications, and opt for mutability when performance or frequent updates are priorities. Understanding these trade-offs and leveraging the right tools will help you write robust, maintainable JavaScript code.</p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>For further exploration, check out the official documentation:</p>
<ul>
<li><a href="https://immutable-js.com/">Immutable.js</a></li>
<li><a href="https://immerjs.github.io/immer/">Immer</a></li>
<li><a href="https://github.com/rtfeldman/seamless-immutable">Seamless-Immutable</a></li>
<li><a href="https://github.com/swannodette/mori">Mori</a></li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>By mastering immutability, you can build more predictable and scalable JavaScript applications, whether you&#x2019;re managing state in a React app or handling complex data transformations.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Understanding SQL Execution Plans]]></title><description><![CDATA[A database execution plan is a detailed roadmap generated by a database management system (DBMS) to illustrate how a specific SQL query will be executed]]></description><link>https://shiftasia.com/community/understanding-sql-execution-plans/</link><guid isPermaLink="false">6931c52918cce10001f0d0f2</guid><category><![CDATA[Database]]></category><dc:creator><![CDATA[King]]></dc:creator><pubDate>Thu, 11 Dec 2025 04:10:08 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/images-2.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://shiftasia.com/community/content/images/2025/12/images-2.jpg" alt="Understanding SQL Execution Plans"><p>When working with databases, writing a query is only half the battle. Understanding how that query actually executes is crucial for optimizing performance and building efficient applications. This is where SQL execution plans come into play&#x2014;they&apos;re your window into the database engine&apos;s decision-making process.</p>
<h2 id="what-is-an-execution-plan">What is an Execution Plan?</h2>
<p>An execution plan is essentially a roadmap that shows how the database engine processes your SQL query. Think of it like a recipe: it breaks down the query into discrete steps, showing the order of operations, which indexes are used, how tables are joined, and the estimated cost of each operation.</p>
<p>The database query optimizer generates this plan by analyzing multiple possible strategies and selecting what it believes to be the most efficient approach based on statistics about your data, available indexes, and system resources.</p>
<h2 id="why-execution-plans-matter">Why Execution Plans Matter</h2>
<p>Performance issues in database applications often stem from inefficient queries rather than hardware limitations. A query that takes seconds instead of milliseconds can cripple an application&apos;s responsiveness. Execution plans help you identify bottlenecks like table scans on large tables, missing indexes, inefficient join strategies, or outdated statistics that lead the optimizer astray.</p>
<p>By examining execution plans, you can transform a query from unusable to lightning-fast, often with minor adjustments to indexes or query structure.</p>
<h2 id="types-of-execution-plans">Types of Execution Plans</h2>
<p>There are two primary types of execution plans you&apos;ll encounter:</p>
<p><strong>Estimated Execution Plans</strong> show what the optimizer predicts will happen without actually running the query. These are generated quickly and are useful for examining query structure without the overhead of execution. However, they&apos;re based on statistics and assumptions that may not reflect reality.</p>
<p><strong>Actual Execution Plans</strong> capture what really happened during query execution. These include actual row counts, execution times, and resource usage. While they require running the query, they provide the truth about performance and can reveal discrepancies between what the optimizer predicted and what actually occurred.</p>
<h2 id="how-to-view-execution-plans">How to View Execution Plans</h2>
<p>The method varies by database system, but most provide straightforward ways to access plans:</p>
<p>In SQL Server, you can prefix your query with <code>SET SHOWPLAN_ALL ON</code> or use SQL Server Management Studio&apos;s &quot;Display Estimated Execution Plan&quot; and &quot;Include Actual Execution Plan&quot; buttons. These generate graphical representations that are intuitive to read.</p>
<p>PostgreSQL users can add <code>EXPLAIN</code> before any query to see the plan, or <code>EXPLAIN ANALYZE</code> to get the actual execution plan with timing information. The output is text-based but highly detailed.</p>
<p>MySQL offers the <code>EXPLAIN</code> keyword similarly, showing information about table access methods and join types. Oracle provides <code>EXPLAIN PLAN FOR</code> followed by your query, with results viewable through specific system tables.</p>
<h2 id="reading-an-execution-plan">Reading an Execution Plan</h2>
<p>Execution plans can seem overwhelming at first, but they follow logical patterns. Operations are typically displayed hierarchically, either top-to-bottom or left-to-right depending on your tool. The query optimizer processes operations in a specific order, often from the innermost operations outward.</p>
<p>Each operation in the plan includes valuable information: the operation type (like Index Seek, Table Scan, or Hash Join), estimated and actual row counts, estimated cost (usually shown as a percentage of the total query cost), and details about which objects (tables, indexes) are involved.</p>
<h2 id="common-operations-youll-encounter">Common Operations You&apos;ll Encounter</h2>
<p><strong>Table Scan</strong> means the database reads every row in a table sequentially. This is expensive for large tables and often indicates a missing index. While acceptable for small tables, it&apos;s a red flag for tables with thousands or millions of rows.</p>
<p><strong>Index Scan</strong> reads all entries in an index, which is typically faster than a table scan but still processes more data than necessary. It suggests the index exists but isn&apos;t being used optimally.</p>
<p><strong>Index Seek</strong> is what you want to see&#x2014;the database uses an index to jump directly to relevant rows. This is highly efficient and indicates good index utilization.</p>
<p><strong>Nested Loop Join</strong> processes one row from the outer table and finds matching rows in the inner table, repeating for each outer row. This works well when the outer table is small or when good indexes exist on the join columns.</p>
<p><strong>Hash Join</strong> builds a hash table from one input and probes it with the other. This is efficient for large datasets without suitable indexes.</p>
<p><strong>Merge Join</strong> requires both inputs to be sorted on the join keys, then merges them together. This is very efficient when data is already sorted or when indexes provide sorted output.</p>
<h2 id="key-metrics-to-monitor">Key Metrics to Monitor</h2>
<p>The <strong>cost estimate</strong> represents the optimizer&apos;s prediction of resource usage. Higher percentages indicate operations consuming more resources relative to the total query. Focus optimization efforts on the highest-cost operations.</p>
<p><strong>Row counts</strong> reveal how many rows each operation processes. Large discrepancies between estimated and actual counts suggest outdated statistics, which can lead the optimizer to choose poor strategies.</p>
<p><strong>I/O statistics</strong> show how much data is read from disk versus memory. High physical reads indicate the query is hitting disk frequently, suggesting opportunities for better indexing or memory configuration.</p>
<h2 id="practical-optimization-strategies">Practical Optimization Strategies</h2>
<p>When you identify a table scan on a large table, adding an appropriate index often provides dramatic improvement. The index should cover the columns in your WHERE clause, JOIN conditions, and ideally your SELECT columns too.</p>
<p>If the optimizer chooses a plan different from what you expect, updating statistics can help. Statistics become stale as data changes, causing the optimizer to make decisions based on outdated information. Most databases provide commands to update statistics manually or can be configured to update them automatically.</p>
<p>Sometimes rewriting the query itself produces better results. Breaking complex queries into smaller steps with temporary tables, reformulating subqueries as joins, or using common table expressions can all influence the execution plan positively.</p>
<h2 id="advanced-considerations">Advanced Considerations</h2>
<p>Query hints allow you to override the optimizer&apos;s decisions when you have specific knowledge it lacks. However, use these sparingly&#x2014;they can backfire when data patterns change, and they prevent the optimizer from adapting to new conditions.</p>
<p>Parameter sniffing occurs when the optimizer creates a plan based on the first parameter values it sees, which may not be optimal for other values. This can cause the same query to perform differently with different parameters.</p>
<p>Parallelism allows the database to split operations across multiple processors. While this can dramatically speed up large queries, it adds overhead and isn&apos;t always beneficial for smaller operations.</p>
<h2 id="real-world-example">Real-World Example</h2>
<p>Consider a query that searches for orders from a specific customer in the last month. Without an index, the execution plan might show a table scan reading millions of order records. After adding a composite index on customer ID and order date, the plan changes to an index seek, reading only the relevant hundreds of records&#x2014;a transformation from seconds to milliseconds.</p>
<h2 id="best-practices">Best Practices</h2>
<p>Make execution plan analysis a regular part of your development workflow. Review plans for all important queries before deploying to production. Monitor production queries and regularly examine the most expensive ones. Keep database statistics current through regular updates or automatic maintenance. Test queries with realistic data volumes, as execution plans can differ dramatically between empty development databases and production systems with millions of rows.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Execution plans are your most powerful tool for understanding and optimizing database query performance. While they can seem complex initially, learning to read them transforms database optimization from guesswork into a systematic process. The investment in understanding execution plans pays dividends in faster applications, lower resource costs, and more scalable systems. Start with simple queries, gradually build your interpretation skills, and you&apos;ll soon find yourself instinctively recognizing inefficient patterns and knowing exactly how to fix them.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Discover Knowledge Swapping via AI Approach Learning and Unlearning]]></title><description><![CDATA[<p>This blog will introduce an innovative AI approach that combines learning new knowledge and learning before forgetting to help models adapt to new information while discarding outdated or sensitive data. This method is called Knowledge Swapping and together we will explore how it works through the agenda below:</p><ol><li><strong>Introduction</strong></li><li><strong>Learning</strong></li></ol>]]></description><link>https://shiftasia.com/community/discover-knowledge-swapping-via-ai-approach-learning-and-unlearning/</link><guid isPermaLink="false">691e724a18cce10001f0b4bb</guid><category><![CDATA[MLOps]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Timo]]></dc:creator><pubDate>Thu, 11 Dec 2025 04:04:30 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/11/Designer--2-.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/11/Designer--2-.png" alt="Discover Knowledge Swapping via AI Approach Learning and Unlearning"><p>This blog will introduce an innovative AI approach that combines learning new knowledge and learning before forgetting to help models adapt to new information while discarding outdated or sensitive data. This method is called Knowledge Swapping and together we will explore how it works through the agenda below:</p><ol><li><strong>Introduction</strong></li><li><strong>Learning and Unlearning in AI</strong></li><li><strong>Knowledge Swapping &amp; Architecture</strong></li><li><strong>Apply to projects</strong></li><li><strong>Conclusion</strong></li></ol><h2 id="iintroduction">I - Introduction</h2><p>In recent days, AI has been growing rapidly across many fields including chatbots, warning systems, and forecasting applications. Most people expect AI systems to perform well and deliver high accuracy, which requires training on massive datasets that&apos; a critical factor for success. However, this creates a major challenge: AI models tend to retain everything they learn, making it difficult to remove outdated, biased, or sensitive information once it has been absorbed.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/11/Designer--4-.png" class="kg-image" alt="Discover Knowledge Swapping via AI Approach Learning and Unlearning" loading="lazy" width="1536" height="1024" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/Designer--4-.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/Designer--4-.png 1000w, https://shiftasia.com/community/content/images/2025/11/Designer--4-.png 1536w" sizes="(min-width: 720px) 720px"></figure><h3 id="1-privacy-data">1. Privacy data</h3><p>AI systems must be able to remove sensitive or copyrighted data that they do not have permission to use. This requirement is reinforced by global regulations such as the General Data Protection Regulation (GDPR), which came into effect in Europe in 2018. A real-world example is the lawsuit filed by The New York Times against OpenAI, alleging copyright violations due to training on NYT articles without authorization. These cases highlight the growing need for mechanisms like machine unlearning to ensure compliance and protect both privacy and intellectual property</p><h3 id="2-bias">2. Bias</h3><p>Most AI models are trained on historical datasets that can quickly become outdated. This lack of timely updates often results in lower model quality and inaccurate forecasts, especially in dynamic fields such as finance, healthcare, and technology. Without effective strategies to refresh or replace obsolete knowledge, AI systems risk making decisions based on stale information.</p><h3 id="3-high-cost">3. High cost</h3><p>Because training a state-of-the-art AI model requires substantial resources including millions of dollars and months of computation, retraining a model from scratch every time accuracy drops or data needs to be removed is impractical. Instead, emerging techniques such as machine unlearning and knowledge swapping provide cost-effective solutions to update models without starting over.</p><p>Before diving into the details, the diagram below illustrates the relationship between Continual Learning, Machine Unlearning, and Knowledge Swapping.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/11/img.png" class="kg-image" alt="Discover Knowledge Swapping via AI Approach Learning and Unlearning" loading="lazy" width="1222" height="974" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/img.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/img.png 1000w, https://shiftasia.com/community/content/images/2025/11/img.png 1222w" sizes="(min-width: 720px) 720px"></figure><h2 id="iilearning-to-unlearn">II - Learning to Unlearn</h2><p>In this section, we will explore key concepts in Artificial Intelligence (AI) that revolve around how systems learn, adapt, and even forget information.	</p><h3 id="1-what-is-machine-learning-ml">1. What is Machine Learning (ML)? </h3><p>Machine learning is an exciting field and a core subset of artificial intelligence. It empowers systems to learn from data and improve over time without being explicitly programmed.<br>Instead of hardcoding rules, ML algorithms identify patterns and make predictions or decisions based on experience.<br>You can continue read more about ML <a href="https://shiftasia.com/community/how-to-choose-and-build-the-right-machine-learning-model/">here</a>.</p><h3 id="2-what-is-continuous-learning-cl">2. What is Continuous Learning (CL)?</h3><p>Opposite with traditional ML, when new data arrives, the model typically needs to be re-trained from scratch or fine-tuned on the updated dataset. CL are designed to learn incrementally from new data without full retraining. Instead of starting over, they update their parameters as new samples arrive. This is often implemented using online learning or incremental learning techniques.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/11/Designer--5-.png" class="kg-image" alt="Discover Knowledge Swapping via AI Approach Learning and Unlearning" loading="lazy" width="1536" height="1024" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/Designer--5-.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/Designer--5-.png 1000w, https://shiftasia.com/community/content/images/2025/11/Designer--5-.png 1536w" sizes="(min-width: 720px) 720px"></figure><p>CL is important because of CL will enables models to:</p><ul><li><strong>Adaptability</strong>: Learn from new data in real time without full retraining.</li><li><strong>Retention of Information</strong>: Avoid catastrophic forgetting by preserving past knowledge.</li><li><strong>Generalization</strong>: Stay robust and accurate as environments evolve and data distributions shift.</li></ul><p>These are common categories of methods used in CL models:</p><ul><li><strong>Regularization-Based methods</strong>: To prevent catastrophic forgetting, a penalty term is added to the loss function during training on the new data.<br><em>Example: Elastic Weight Consolidation (EWC), Synaptic Intelligence (SI), L2 Regularization, ...</em></li><li><strong>Memory-Based methods</strong>: To maintain good performance on old data, memory-based methods store or replay data from previous data in a memory buffer.<br><em>Example: Biased Memory Keeping Protocol (BMKP), ...</em></li><li><strong>Architecture-Based methods</strong>: To expand models and adapt to newly arriving data.<br><em>Example: </em>Progressive Neural Networks, Dynamic Expansion, Parameter Isolation, ...</li></ul><h3 id="3-what-is-machine-unlearning-mu">3. What is Machine Unlearning (MU)?</h3><p>MU is the process of removing the influence of specific data points such as sensitive or incorrect data from a trained model without retraining from scratch.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/11/image-7.png" class="kg-image" alt="Discover Knowledge Swapping via AI Approach Learning and Unlearning" loading="lazy" width="1325" height="727" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/image-7.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/image-7.png 1000w, https://shiftasia.com/community/content/images/2025/11/image-7.png 1325w" sizes="(min-width: 720px) 720px"></figure><p>The Importance of Machine Unlearning:</p><ul><li><strong>Legal: </strong>Organizations must comply with requests to remove personal data from models. Regulations like the General Data Protection Regulation (GDPR) in the European Union grant individuals the &#x201C;right to be forgotten.&#x201D;</li><li><strong>Privacy compliance: </strong>This establishes a <strong>positive image</strong> of the organization in the eyes of the public. Building trust and transparency, establishing a positive image of the organization in the eyes of the public.</li><li><strong>Security: </strong>This reduces risk from leaked, malicious, or compromised data. Removing certain data points from a trained machine-learning model without needing to retrain the entire model from scratch</li><li><strong>Correctness: </strong>helps fix errors efficiently, ensuring models remain accurate and reliable without costly full retraining.</li></ul><p>These MU approaches:</p><ul><li><strong>Fine-Tuning</strong>: Retrain the model on the remaining data after removing the target samples. <a href="https://shiftasia.com/community/fine-tuning-vs-prompt-tuning-when-to-use-which/">here</a></li><li><strong>Influence Function</strong>: Estimate how much a training point influences the model&#x2019;s parameters or predictions using second-order derivatives.</li><li><strong>NegGrad+</strong>: To balance the retention of useful knowledge with the removal of influence from the target data</li><li><strong>L1-Sparse</strong>: Use L1 regularization to enforce sparsity when adjusting parameters, minimizing unnecessary changes by driving insignificant weights toward zero.</li><li><strong>Relabeling</strong>: Change labels of removed data to neutral or random values before retraining, reducing their influence.</li></ul><h2 id="iiiknowledge-swapping">III - Knowledge Swapping</h2><p>Knowledge Swapping refers to the process of suppressing redundant parameters, selectively retaining crucial parameters, and acquiring new knowledge simultaneously within a pre-trained model. This technique enables models to adapt without full retraining while ensuring compliance with privacy and correctness requirements.</p><p>There are three core aims: Forgetting old data, Retaining useful knowledge, Learning new data. And knowledge swapping involves two main processes: learning and forgetting.</p><ul><li><strong>Forget</strong>: Remove unwanted or sensitive knowledge from the model.</li><li><strong>Retain:</strong> Preserve useful knowledge that is still relevant for future tasks.</li><li><strong>Learn</strong>: Introduce new or clean knowledge from a trusted source.</li></ul><p><strong>There are two key strategies define the architecture of Knowledge Swapping:</strong></p><ul><li><strong>Forgetting before Learning </strong>( F &#x2192; L): Forget old data first, then learn new data.</li><li><strong>Learn before Forget </strong>(L &#x2192; F): Learn new data first, then forget old data.</li></ul><p>Comparing between F &#x2192; L and L &#x2192; F of Knowledge Swapping:</p><!--kg-card-begin: html-->
<div style="overflow-x: auto; max-width: -webkit-fill-available;">
  <table border="1" cellpadding="8" cellspacing="0" style="border-collapse: collapse; width: 100%; max-width: -webkit-fill-available;">
    <thead style="background-color: #f2f2f2;">
      <tr>
        <th></th>
        <th>F &#x2192; L</th>
        <th>L &#x2192; F</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><strong>Parameter Update Direction</strong></td>
        <td>The principal changes are concentrated in the <strong>earlier layers</strong>,<br> which produce <strong>low-level feature representations</strong>.</td>
        <td>The majority of parameter updates occur in the <strong>later layers</strong> of the neural network,<br> which are responsible for generating <strong>semantic-level features</strong>.</td>
      </tr>
      <tr>
        <td><strong>Parameter Stability</strong></td>
        <td><strong>Low stability</strong></td>
        <td><strong>High stability</strong></td>
      </tr>
      <tr>
        <td><strong>Accuracy Impact</strong></td>
        <td><strong>Typically fails</strong> to achieve complete forgetting. 
            <br> The accuracy of the forgetting set <strong>increases again</strong> <br>after the learning phase.</td>
        <td>Successful and complete forgetting. <br>The accuracy of the forgetting set decreases to <strong>nearly 0%</strong>.</td>
      </tr>
    </tbody>
  </table>
</div>
<!--kg-card-end: html--><p></p><p>In summary, L &#x2192; F demonstrates higher parameter stability and achieves nearly complete forgetting (accuracy close to 0%), while F &#x2192; L often struggles with full forgetting and shows accuracy rebound after learning.</p><h2 id="vapply-to-projects">V - Apply to projects</h2><p>Knowledge Swapping is not just a theoretical concept, it offers practical solutions for real-world AI challenges. Below are key areas where this approach can be applied:</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/11/image-6.png" class="kg-image" alt="Discover Knowledge Swapping via AI Approach Learning and Unlearning" loading="lazy" width="1536" height="1024" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/image-6.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/image-6.png 1000w, https://shiftasia.com/community/content/images/2025/11/image-6.png 1536w" sizes="(min-width: 720px) 720px"></figure><h3 id="1-image-classification">1. <a href="https://github.com/xingmingyu123456/KnowledgeSwapping/tree/main/image-classification">Image classification</a></h3><p>In computer vision projects, models often need to adapt to new categories or remove outdated ones. For example, an e-commerce platform may need to add new product classes while removing discontinued items. Knowledge Swapping enables this update without retraining the entire model, saving time and cost.</p><h3 id="2-object-detection">2. <a href="https://github.com/xingmingyu123456/KnowledgeSwapping/tree/main/object-detection">Object detection</a></h3><p>Autonomous driving systems or surveillance applications frequently encounter changes in object sets (e.g., new traffic signs or removal of obsolete ones). Knowledge Swapping allows models to integrate these changes efficiently while maintaining detection accuracy.</p><h3 id="3-semantic-segmentation">3. <a href="https://github.com/xingmingyu123456/KnowledgeSwapping/tree/main/semantic-segmentation">Semantic segmentation</a></h3><p>Healthcare imaging or geographic mapping projects require precise segmentation of regions. When new labels are introduced or old ones become irrelevant, Knowledge Swapping helps update the segmentation model without catastrophic forgetting, ensuring consistent performance.</p><h2 id="viconclusion">VI - Conclusion</h2><p>To summarize, <strong>Knowledge Swapping</strong>, as introduced by <strong>Mingyu Xing et al</strong>., is a significant step toward building robust and adaptive AI models. By prioritizing learning before forgetting, this approach effectively addresses critical challenges in real-world applications without requiring full retraining. This makes Knowledge Swapping a practical and forward-thinking solution for modern AI systems.</p><h2 id="documents">Documents</h2><ol><li><a href="https://arxiv.org/pdf/2502.08075">Knowledge Swapping via Learning and Unlearning</a></li><li><a href="https://github.com/xingmingyu123456/KnowledgeSwapping">GitHub Knowledge Swapping</a></li><li><a href="https://www.library.hbs.edu/working-knowledge/qa-seth-neel-on-machine-unlearning-and-the-right-to-be-forgotten">How to Make AI &apos;Forget&apos; All the Private Data It Shouldn&apos;t Have</a></li><li><a href="https://www.researchgate.net/publication/370763971_Learn_to_Unlearn_A_Survey_on_Machine_Unlearning">Learn to Unlearn: A Survey on Machine Unlearning</a></li><li><a href="https://shiftasia.com/community/how-to-choose-and-build-the-right-machine-learning-model/">How to Choose and Build the Right Machine Learning Model</a></li><li><a href="https://shiftasia.com/community/fine-tuning-vs-prompt-tuning-when-to-use-which/">Fine-tuning vs. Prompt-tuning: When to Use Which</a></li></ol>]]></content:encoded></item><item><title><![CDATA[Evaluating Vector Search Quality: A Practical Guide for Developers]]></title><description><![CDATA[<p>Vector databases and embeddings have become core infrastructure for AI applications&#x2013;search, RAG, recommendations, anomaly detection, and more. But while building a vector search system is straightforward, <strong>measuring its quality</strong> is not. Developers often optimize models, indexes, or parameters without proper evaluation, leading to misleading performance and poor user</p>]]></description><link>https://shiftasia.com/community/evaluating-vector-search-quality/</link><guid isPermaLink="false">692d179818cce10001f0cab8</guid><category><![CDATA[AI]]></category><dc:creator><![CDATA[MINATO Nguyen]]></dc:creator><pubDate>Sat, 06 Dec 2025 04:29:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/evalfe.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/12/evalfe.jpg" alt="Evaluating Vector Search Quality: A Practical Guide for Developers"><p>Vector databases and embeddings have become core infrastructure for AI applications&#x2013;search, RAG, recommendations, anomaly detection, and more. But while building a vector search system is straightforward, <strong>measuring its quality</strong> is not. Developers often optimize models, indexes, or parameters without proper evaluation, leading to misleading performance and poor user experience.</p><p>This article provides a clear framework for <strong>evaluating vector search quality</strong>, including metrics, datasets, and practical workflows you can apply immediately.</p><h1 id="why-vector-search-needs-proper-evaluation">Why Vector Search Needs Proper Evaluation</h1><p>Traditional keyword search can be tested with precision/recall and simple heuristics, but vector search is different:</p><ul><li>Results depend on <strong>embedding models</strong>.</li><li>Index configurations affect accuracy vs speed.</li><li>Relevant results may not be strictly &quot;correct&quot; or &quot;incorrect&quot;.</li><li>Real-world meaning similarity is subjective.</li></ul><p>Without structured evaluation, you might ship a system that feels good in small tests but fails at scale</p><h1 id="key-metrics-for-vector-search-quality">Key Metrics for Vector Search Quality</h1><ol><li><strong>Recall@K (Most Common)</strong><br><strong>Recall@K</strong> measures how many of the &quot;true most similar&quot; items are found within the top K results.<br>	-	<strong>Recall@10</strong> = proportion of correct neighbors found in the top 10.<br>	-	Higher recall means your yndex retrieves results close to the brute-force (ground truth).</li><li><strong>Precision@K</strong><br>Measures how many of the returned top-K results are actually relevant. This method is useful when you evaluation dataset contains <strong>multiple relevant answers</strong> instead of exact nearest neighbors.</li><li><strong>Mean Reciprocal Rank (MRR)</strong><br>Focuses on where the <strong>first correct result</strong> appears.<br>	-	High MRR = relevant items appear very early in the list.<br>	-	Common in question-answer similarity search.</li><li><strong>Normalized Discounted Cumulative Gain (NDCG)</strong><br>NDCG evaluates graded relevance:<br>	-	Works when results are &quot;somewhat relevant&quot;, &quot;very relevant&quot;, etc.<br>	-	Discounts results based on ranking position.<br>Often used in recommendation systems and semantic search.</li><li><strong>Latency and Throughput Metrics</strong><br>Quality is not only accuracy &#x2013; performance matters.<br>	-	P95/P99 latency<br>	-	Queries per second (QPS)<br>	-	Index build time<br>	-	Memory usage<br>A high-recall index is useless if it&apos;s too slow for production.</li></ol><h1 id="evaluation-workflow">Evaluation workflow</h1><ol><li>Build or collect a ground-truth dataset</li><li>Generate embeddings</li><li>Compute brute-force (&quot;gold standard&quot;) neighbors</li><li>Test different vector search configurations</li><li>Plot accuracy vs speed.</li></ol><h1 id="sample-workflow">Sample Workflow</h1><ol><li>Install and import dependencies:</li></ol><!--kg-card-begin: markdown--><p><code>pip install chromadb sentence-transformers</code></p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code>from sentence_transformers import SentenceTransformer
import chromadb
import numpy as np
</code></pre>
<!--kg-card-end: markdown--><p>2. &#xA0; Generate embeddings</p><!--kg-card-begin: markdown--><pre><code>model = SentenceTransformer(&quot;all-MiniLM-L6-v2&quot;)

documents = [&quot;Apple fruit&quot;, &quot;Orange fruit&quot;, &quot;Carrot vegetable&quot;]
doc_ids = [&quot;doc1&quot;, &quot;doc2&quot;, &quot;doc3&quot;]

embeddings = model.encode(documents).tolist()</code></pre>
<!--kg-card-end: markdown--><p>3. &#xA0; Create a Chroma collection and and documents</p><!--kg-card-begin: markdown--><pre><code>client = chromadb.Client()

collection = client.create_collection(&quot;fruits_collection&quot;)

collection.add(
    ids=doc_ids,
    documents=documents,
    embeddings=embeddings
)</code></pre>
<!--kg-card-end: markdown--><p>4. &#xA0; Query the collection</p><!--kg-card-begin: markdown--><pre><code>query = &quot;I like fruits&quot;
query_emb = model.encode([query]).tolist()

results = collection.query(
    query_embeddings=query_emb,
    n_results=2
)

print(results)
</code></pre>
<!--kg-card-end: markdown--><p>Example output:</p><!--kg-card-begin: markdown--><pre><code>{
    &apos;ids&apos;: [[&quot;doc1&quot;, &quot;doc2&quot;]],
    &apos;documents&apos;: [[&quot;Apple fruit&quot;, &quot;Orange fruit&quot;]],
    &apos;distance&apos;: [[0.12, 0.15]]
}</code></pre>
<!--kg-card-end: markdown--><p>5. &#xA0; Evaluate Recall@K</p><!--kg-card-begin: markdown--><pre><code>ground_truth = [[&quot;doc1&quot;, &quot;doc2&quot;]]

predicted_ids = results[&quot;ids&quot;]
recall = np.mean([len(set(pred) &amp; set(gt))/len(gt)
                  for pred, gt in zip(predicted_ids, ground_truth)])
                
print(&quot;Recall@K: &quot;, recall)</code></pre>
<!--kg-card-end: markdown--><p>6. &#xA0; Experiment with different settings</p><ul><li>Change <strong>embedding models</strong></li><li>Use <strong>different collection parameters</strong> (e.g., metric=&quot;cosine&quot;)</li><li>Measure <strong>latency</strong> and <strong>accuracy trade-offs</strong></li></ul><!--kg-card-begin: markdown--><pre><code>import time
start = time.time()
collection.query(query_embeddings=query_emb, n_results=2)
print(&quot;Query latency: &quot;, time.time() - start, &quot;seconds&quot;)
</code></pre>
<!--kg-card-end: markdown--><h1 id="conclusion">Conclusion</h1><p>Evaluating vector search quality is not just about picking the best embedding or the fastest index. It&apos;s about finding the best balance between:</p><ul><li>Accuracy</li><li>Latency</li><li>Memory</li><li>Real-world relevance</li></ul><p>A robust evaluation pipeline will ensure your vector search system stays reliable as your data and traffic scale.</p>]]></content:encoded></item><item><title><![CDATA[Say Goodbye to JavaScript: Building Web Apps with Pure Python using Reflex]]></title><description><![CDATA[<p>Hey everyone! ? Ever wish you could build beautiful, fast web applications without touching a single line of JavaScript? If you&apos;re a Pythonista like me, you know the pain of having to switch context to front-end frameworks like React.</p><p>Well, I recently found a game-changer called Reflex (it used</p>]]></description><link>https://shiftasia.com/community/say-goodbye-to-javascript-building-web-apps-with-pure-python-using-reflex/</link><guid isPermaLink="false">692aa76918cce10001f0c674</guid><category><![CDATA[front-end]]></category><category><![CDATA[back-end]]></category><dc:creator><![CDATA[Fred Pham]]></dc:creator><pubDate>Sat, 06 Dec 2025 04:20:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/11/Reflex-Thumbnail.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/11/Reflex-Thumbnail.png" alt="Say Goodbye to JavaScript: Building Web Apps with Pure Python using Reflex"><p>Hey everyone! ? Ever wish you could build beautiful, fast web applications without touching a single line of JavaScript? If you&apos;re a Pythonista like me, you know the pain of having to switch context to front-end frameworks like React.</p><p>Well, I recently found a game-changer called Reflex (it used to be called Pynecone), and it lets you build your entire full-stack web app&#x2014;front-end and back-end&#x2014;all in pure, idiomatic Python. Seriously. It compiles your Python code into a modern React app!</p><h2 id="what-is-reflex">What is Reflex?</h2><p>Think of Reflex as a framework that gives you the best of both worlds: the simplicity and power of Python combined with the modern speed of a React front-end.</p><ul><li>Python Everywhere: Define your UI, your state, and your back-end logic&#x2014;all in Python.</li><li>Built-in State Management: Managing component state and events is super easy and intuitive.</li><li>Ready-to-Go Components: It comes with a massive library of ready-made components, so you don&apos;t have to style everything from scratch.</li><li>Fast Development: You can go from zero to a live app incredibly quickly.</li></ul><h2 id="lets-build-a-quick-demo-app">Let&apos;s Build a Quick Demo App</h2><p>To show you how easy it is to manage data and lists, we&apos;ll look at two common app patterns: a simple To-Do List and a basic Student List.</p><p>First things first, install Reflex and initialize a new project:</p><pre><code>pip install reflex
reflex init</code></pre><p>This sets up all the basic files you need.</p><p>Now, you define a list of tasks in Python, create an input field and a button, and Reflex takes care of updating everything in the browser when you add a new task. No JavaScript needed for dynamic updates!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://shiftasia.com/community/content/images/2025/11/Reflex-Todo-Demo.png" class="kg-image" alt="Say Goodbye to JavaScript: Building Web Apps with Pure Python using Reflex" loading="lazy" width="1402" height="663" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/Reflex-Todo-Demo.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/Reflex-Todo-Demo.png 1000w, https://shiftasia.com/community/content/images/2025/11/Reflex-Todo-Demo.png 1402w" sizes="(min-width: 720px) 720px"><figcaption>Todo List Demo</figcaption></figure><p>What about handling more complex data, like a student list that needs to be loaded from a database? This is where Reflex&apos;s state management really shines.</p><p>No need to fuss with HTML table structure or CSS styling; you get a clean, professional-looking table right out of the box!</p><p>And here&apos;s an example of a Student List:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://shiftasia.com/community/content/images/2025/11/Reflex-Student-List.gif" class="kg-image" alt="Say Goodbye to JavaScript: Building Web Apps with Pure Python using Reflex" loading="lazy" width="1280" height="680"><figcaption>Student List Demo</figcaption></figure><p>When your Python code starts the data-fetching process (which usually takes a moment), you simply flip a boolean state variable, say <code>State.loading=True</code>. Reflex automatically detects this change and lets you instantly swap the main content for a clean loading screen.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://shiftasia.com/community/content/images/2025/11/Reflex-Code.png" class="kg-image" alt="Say Goodbye to JavaScript: Building Web Apps with Pure Python using Reflex" loading="lazy" width="1246" height="1153" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/Reflex-Code.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/Reflex-Code.png 1000w, https://shiftasia.com/community/content/images/2025/11/Reflex-Code.png 1246w" sizes="(min-width: 720px) 720px"><figcaption>Create a web application with just a simple python script.</figcaption></figure><p>After you write the Python code for these demos, you just run <code>reflex run</code>, and your browser magic begins at <code>http://localhost:3000</code>!</p><h2 id="final-thoughts">Final Thoughts</h2><p>Reflex can handle the complexity of the front-end, from state management to UI updates, so you can focus on the business logic in the language you love.</p><p>It&apos;s fast, fun, and makes the development process feel incredibly streamlined. Go give it a try! You might just find your new favorite way to build web apps.</p><p>Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[A Simple CSS Selector That Most Devs Never Try - the :has() Selector]]></title><description><![CDATA[<p>If you ask a group of developers: &#x201C;Hey, have you used <code>:has()</code> before?&#x201D;<br>Most of them will look at you like: <em>&#x201C;Bro, is that even real CSS?&#x201D;</em></p><p>Yes. It is real. It is powerful. And honestly&#x2026; it feels a bit illegal because CSS is not</p>]]></description><link>https://shiftasia.com/community/a-simple-css-selector-that-most-devs-still-havent-tried/</link><guid isPermaLink="false">692e547718cce10001f0cc68</guid><category><![CDATA[front-end]]></category><dc:creator><![CDATA[Neji]]></dc:creator><pubDate>Sat, 06 Dec 2025 04:08:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/has_selector.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/12/has_selector.png" alt="A Simple CSS Selector That Most Devs Never Try - the :has() Selector"><p>If you ask a group of developers: &#x201C;Hey, have you used <code>:has()</code> before?&#x201D;<br>Most of them will look at you like: <em>&#x201C;Bro, is that even real CSS?&#x201D;</em></p><p>Yes. It is real. It is powerful. And honestly&#x2026; it feels a bit illegal because CSS is not supposed to be this smart. But here we are.</p><p>Today I want to share this &#x201C;new old&#x201D; CSS superpower that can change how you build UI logic &#x2014; without JavaScript. And trust me, you will feel like a magician.</p><hr><h2 id="what-is-has">What Is <code>:has()</code>?</h2><p>The official definition is something like:</p><blockquote>&#x201C;Select an element if it contains something that matches the selector inside.&#x201D;</blockquote><p>But in simple language:<br><strong><code>:has()</code> is the closest thing we have to a &#x201C;parent selector&#x201D; in CSS.</strong></p><p>With <code>:has()</code>, you can style a parent based on what the child looks like.</p><p>Something like:</p><pre><code class="language-css">.card:has(img) {
  border: 2px solid blue;
}
</code></pre><p>Boom.<br>If <code>.card</code> contains an <code>&lt;img&gt;</code>, it becomes blue.<br>CSS just checked the inside and reacted.</p><hr><h2 id="why-it-feels-like-css-with-superpowers">Why It Feels Like CSS With Superpowers</h2><p>Before <code>:has()</code>, CSS always felt like working with strict Vietnamese parents:</p><!--kg-card-begin: markdown--><ul>
<li>
<p>You can look at your children (descendant selectors)</p>
</li>
<li>
<p>But you cannot look at your parents</p>
</li>
<li>
<p>No arguments, no exceptions :))</p>
</li>
</ul>
<!--kg-card-end: markdown--><p>But now <code>:has()</code> says:<br><strong>&#x201C;Don&#x2019;t worry bro, I can look up, I can look down, I can check neighbors&#x2014; I handle everything.&#x201D;</strong></p><p>Here are some things you can suddenly do:</p><ol><li><strong>Style a form when an input is invalid</strong></li></ol><p>No JS. No event listener. Just CSS.</p><pre><code>form:has(input:invalid) {
  border: 2px solid red;
}
</code></pre><p>Boom. Instant feedback UI.</p><p><strong>2. Change button style when a checkbox is checked</strong></p><p>Classic &#x201C;Enable button when user agrees&#x201D;.</p><pre><code class="language-css">button:has(+ input:checked) {
  background: green;
}
</code></pre><p><strong>3. Accordion without JavaScript</strong></p><p>Yes, you read that right.</p><pre><code class="language-css">.item:has(.content.open) {
  max-height: 200px;
}
</code></pre><p><strong>A Real Example (Dev-Friendly)</strong></p><p>Let&#x2019;s say you want to highlight a <code>.product-card</code> only when it has <code>.sale-tag</code>.</p><pre><code class="language-css">.product-card:has(.sale-tag) {
  background: #fff7e6;
  border-color: orange;
}
</code></pre><p>Result:<br>When the sale tag appears &#x2192; whole card becomes &#x201C;on sale mode&#x201D;.</p><p>And you didn&#x2019;t write even one line of JavaScript.<br>Feels good right?</p><hr><h2 id="browser-support">Browser Support?</h2><p>Good news:</p><!--kg-card-begin: markdown--><ul>
<li>
<p>Chrome &#x2714;</p>
</li>
<li>
<p>Safari &#x2714;</p>
</li>
<li>
<p>Edge &#x2714;</p>
</li>
<li>
<p>Firefox &#x2714;</p>
</li>
</ul>
<!--kg-card-end: markdown--><hr><p><strong>Why Most Devs Don&#x2019;t Use It Yet</strong></p><!--kg-card-begin: markdown--><p>Because:</p>
<ul>
<li>
<p>They don&#x2019;t know</p>
</li>
<li>
<p>They think it&#x2019;s not supported</p>
</li>
<li>
<p>They heard about it once but forgot</p>
</li>
<li>
<p>CSS scares them</p>
</li>
<li>
<p>That mindset of &quot;Just use JavaScript, it&#x2019;s faster.&quot;</p>
</li>
</ul>
<!--kg-card-end: markdown--><p>But once you try <code>:has()</code>, you will realize it&#x2019;s the missing piece we always wanted.</p><hr><h2 id="when-should-you-use-has">When Should You Use <code>:has()</code>?</h2><p>Use it when you want CSS to react to the <em>structure</em> of the HTML.</p><!--kg-card-begin: markdown--><p>Great for:</p>
<ul>
<li>
<p>Forms</p>
</li>
<li>
<p>Cards</p>
</li>
<li>
<p>Interactions</p>
</li>
<li>
<p>Accordions</p>
</li>
<li>
<p>Navigation menus</p>
</li>
<li>
<p>Any &#x201C;state&#x201D; that depends on children</p>
</li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>Not great for:</p>
<ul>
<li>
<p>Complex app logic</p>
</li>
<li>
<p>Heavy UI state (JS v&#x1EAB;n l&#xE0;m t&#x1ED1;t h&#x1A1;n)</p>
</li>
</ul>
<!--kg-card-end: markdown--><hr><h2 id="final-thought">Final Thought</h2><p>The <code>:has()</code> selector is honestly a game changer.<br>It&#x2019;s like the day you learned Flexbox or Grid for the first time &#x2014; your brain expands a little bit.</p><p>With <code>:has()</code> you can:</p><!--kg-card-begin: markdown--><ul>
<li>
<p>Style based on children</p>
</li>
<li>
<p>Create UI states without JS</p>
</li>
<li>
<p>Make smarter components</p>
</li>
<li>
<p>Reduce code complexity</p>
</li>
<li>
<p>Make CSS fun again</p>
</li>
</ul>
<!--kg-card-end: markdown--><p>So next time you code UI, give this selector a try.<br>Maybe you&apos;ll feel like a CSS wizard for 5 minutes.<br>Worth it.</p>]]></content:encoded></item><item><title><![CDATA[CLEAN CODE: GRADE ORANGE]]></title><description><![CDATA[<blockquote>The transition zone</blockquote><h3 id="where-chaos-begins-turning-into-order">Where chaos begins turning into order</h3><p>If the Red zone is where code feels &#x201C;dangerous&#x201D; then the Orange zone is where you can finally breathe a little</p><p>Even though there is still plenty to improve.</p><p>In this state, the code isn&#x2019;t perfect, but</p>]]></description><link>https://shiftasia.com/community/clean-code-grade-orange-buoc-chuyen-minh/</link><guid isPermaLink="false">6924b80a18cce10001f0c05d</guid><category><![CDATA[misc]]></category><dc:creator><![CDATA[ELVIS Pham]]></dc:creator><pubDate>Sat, 06 Dec 2025 03:56:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/11/cleancode_orange-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>The transition zone</blockquote><h3 id="where-chaos-begins-turning-into-order">Where chaos begins turning into order</h3><img src="https://shiftasia.com/community/content/images/2025/11/cleancode_orange-1.png" alt="CLEAN CODE: GRADE ORANGE"><p>If the Red zone is where code feels &#x201C;dangerous&#x201D; then the Orange zone is where you can finally breathe a little</p><p>Even though there is still plenty to improve.</p><p>In this state, the code isn&#x2019;t perfect, but it also doesn&#x2019;t crush your soul.</p><p>This is the <strong>transition zone.</strong></p><p>The place where cleanup becomes <em>possible</em> without the fear that a tiny change will blow up the whole system.</p><h3 id="renaming-variablesa-small-step-huge-impact">Renaming variables - a small step, huge impact</h3><blockquote>Laying the foundation for clarity</blockquote><p>You would be surprised how much clarity you gain just by renaming things:</p><p>		<code>flag &#x2192; isArchived </code><br>		<code>temp &#x2192; initialValue </code><br>		<code>data &#x2192; userResponse</code></p><p>It seems simple, almost trivial, but an intentional name removes so much mental guessing.</p><p>It saves seconds when reading code, and hours for the whole team over a sprint.</p><h3 id="breaking-the-story-into-smaller-chapters">Breaking the story into smaller chapters</h3><p>You encounter a 40-line function handling multiples different responsibilities.</p><p>Instead of rewriting everything, you simply split it out:</p><p>		<code>validateInput() </code><br>		<code>calculateDiscount() </code><br>		<code>saveToDatabase()</code></p><p>We are not changing the logic.</p><p>We are just breaking the story into clearer, digestible pieces so the next person doesn&#x2019;t need to decode everything at once.</p><h2 id="flattening-logic-whenever-possible">Flattening logic whenever possible</h2><p>The Orange zone is where you start using guard clauses to eliminate deep nesting:</p><p>Instead of 4-5 stacked <code>if</code> blocks, you rewrite them as:</p><p>		<code>if (!user) return</code><br>		<code>if (!user.isActive) return</code><br>		<code>if (user.isBlocked) return</code></p><p>Cleaner, flatter, easier to follow.</p><p>This reduces cognitive load and prevents the dreaded &#x201C;nested-if tunnel&#x201D;.</p><h3 id="eliminating-magic-numbers">Eliminating magic numbers</h3><blockquote>When numbers need real names</blockquote><p>		<code>if (status === 3)</code></p><p>Replace that mysterious <em>3</em> with something meaningful:</p><p>		<code>STATUS_ARCHIVED</code></p><p>Or change the number 60 to:</p><p>		<code>SESSION_TIMEOUT</code></p><p>The Orange zone is where you replace hidden meaning with names that everyone understands, even newcomers.</p><h3 id="orange-is-the-launchpad-to-green">Orange is the launchpad to green</h3><p>The Orange zone isn&#x2019;t where we stop, it&#x2019;s where momentum begins.</p><p>It&#x2019;s the stage where small habits compound:</p><ul><li>clearer names</li><li>smaller functions</li><li>flatter logic</li><li>fewer hidden surprises</li></ul><p>These small, consistent improvements gradually push the entire codebase toward the <strong>Green zone.</strong></p><p>A state of stability, clarity, and long-term maintainability.</p><h3 id="references">References</h3><p><a href="https://martinfowler.com/books/refactoring.html">Martin Fowler - Refactoring</a><br><a href="http://butunclebob.com/ArticleS.UncleBob.CleanCodeArgs">Boy Scout Rule &#x2013; Uncle Bob</a></p>]]></content:encoded></item><item><title><![CDATA[Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)]]></title><description><![CDATA[<p><strong>var</strong>, <strong>let </strong>and <strong>const </strong>are used in JavaScript to declare variables, but they differ significantly in their <strong>scope</strong>, <strong>hoisting</strong>, and whether they can be <strong>reassigned </strong>or <strong>redeclared</strong>.</p><p><strong>	1.	var </strong>is the original way to declare variables in JavaScript. It has largely been superseded by let and const due to its</p>]]></description><link>https://shiftasia.com/community/var-let-const-hosting-and-temporal-dead-zone-in-javascript/</link><guid isPermaLink="false">692e5ab618cce10001f0cd4f</guid><category><![CDATA[front-end]]></category><category><![CDATA[WEB]]></category><dc:creator><![CDATA[Gavin Huynh]]></dc:creator><pubDate>Sat, 06 Dec 2025 03:36:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/1_Nvxnq-bqM1iyTqwO_clFYQ-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/12/1_Nvxnq-bqM1iyTqwO_clFYQ-1.jpg" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)"><p><strong>var</strong>, <strong>let </strong>and <strong>const </strong>are used in JavaScript to declare variables, but they differ significantly in their <strong>scope</strong>, <strong>hoisting</strong>, and whether they can be <strong>reassigned </strong>or <strong>redeclared</strong>.</p><p><strong>	1.	var </strong>is the original way to declare variables in JavaScript. It has largely been superseded by let and const due to its often confusing scoping behavior.</p><p>	<strong>Scope</strong>: Function-scoped or globally scoped. Variables declared with var inside a function are only accessible within that function. If declared outside any 			function, they are global. var ignores block scope (i.e., it is visible outside of if 		statements or for loops).</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-6.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="301" height="154"></figure><p>	<strong>Hoisting</strong>: Variables declared with var are hoisted (moved to the top of their scope) and initialized with undefined. This means you can use a var variable before its declaration in the code without an error (though it will be undefined).</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-7.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="315" height="52"></figure><p>	<strong>Reassignment</strong>: Can be reassigned (its value can be changed).</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-10.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="277" height="78"></figure><p>	<strong>Redeclaration</strong>: Can be redeclared within the same scope without error.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-9.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="279" height="81"></figure><p>	<strong>2. </strong> <strong>let </strong>(Modern, Block-Scoped)<br>Introduced in ECMAScript 2015 (ES6), let is the preferred way to declare variables that might need to be reassigned.</p><p><strong>	Scope</strong>: Block-scoped. A variable declared with let is only accessible within the block of code (defined by curly braces {}) in which it&apos;s declared (e.g., inside an if statement, for loop, or a simple block).</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-11.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="456" height="166"></figure><p>	<strong>Hoisting</strong>: Variables declared with let are hoisted but are not initialized. Accessing a let variable before its declaration results in a ReferenceError (this is known as the Temporal Dead Zone).</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://shiftasia.com/community/content/images/2025/12/image-13.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="485" height="82"></figure><p><strong>	Reassignment</strong>: Can be reassigned (its value can be changed).</p><p>	<strong>Redeclaration</strong>: Cannot be redeclared within the same scope. Doing so results in a SyntaxError.</p><p>	<strong>3.</strong>	<strong>const </strong>(Modern, Block-Scoped, Immutable Reference)<br>Also introduced in ES6, const is used to declare variables whose value should remain constant throughout the program&apos;s execution.</p><p>	<strong>Scope</strong>: Block-scoped, just like let.</p><p>	<strong>Hoisting</strong>: Hoisted, but not initialized, resulting in a Temporal Dead Zone.</p><p>	<strong>Reassignment</strong>: Cannot be reassigned (its value cannot be changed after initialization). You must assign a value when declaring it.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-14.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="458" height="57"></figure><p>	<strong>Redeclaration</strong>: Cannot be redeclared within the same scope.</p><p><strong>	4. 	Hoisting</strong></p><p>	Hoisting is a JavaScript mechanism where <strong>variable and function declarations</strong> are moved to the top of their containing scope (either the global scope or the function scope) during the <strong>compilation phase </strong><em>before</em> the code is executed.</p><p>	- <strong>var </strong>variable Hositing</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-15.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="367" height="75"></figure><p>	- <strong>let </strong>Variable Hoisting (with TDZ):</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-16.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="479" height="87"></figure><p>	- <strong>Function Declaration</strong>:</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-17.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="475" height="123"></figure><p>	- <strong>Function Expression:</strong></p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/image-18.png" class="kg-image" alt="Understanding Javascript variables declaration (var, let, const), Hosting mechanism and Temporal dead zone (TDZ)" loading="lazy" width="349" height="107"></figure><p><strong>	5. 	Temporal Dead Zone (TMZ)</strong></p><p>	<strong>The Temporal Dead Zone (TDZ)</strong> is a specific period during the execution of JavaScript code where variables declared with let or const exist but cannot be accessed or assigned a value.</p><p>	If you attempt to access a let or const variable within its TDZ, the JavaScript engine will immediately throw a ReferenceError.</p><p><strong><em> * How the TDZ Works</em></strong><br>	The TDZ is directly tied to the concept of hoisting for let and const:</p><p><strong>	Hoisting Occurs:</strong> Like var, variables declared with let and const are hoisted (their creation is moved) to the top of their scope (which is block scope for these keywords).</p><p><strong>	Uninitialized State:</strong> Unlike var (which is initialized to undefined during hoisting), let and const variables are not initialized when they are hoisted. They are put into an uninitialized state.</p><p><strong>	The TDZ Period:</strong> The TDZ is the time period that begins when the scope is entered (e.g., when a { block is started) and ends when the variable&apos;s declaration line is executed and the variable is assigned a value (initialized).</p><p><strong>	Exiting the TDZ</strong>: Once the JavaScript interpreter reaches and executes the line of code that declares and initializes the variable (e.g., let x = 10; or const PI = 3.14;), the variable exits the TDZ and becomes fully accessible.</p>]]></content:encoded></item><item><title><![CDATA[Understanding MCP: The Model Context Protocol for AI Agents]]></title><description><![CDATA[<p>In the rapidly evolving landscape of Large Language Models (LLMs), the ability to establish dependable communication between models and external systems has become a critical necessity. The <strong>Model Context Protocol (MCP)</strong> has emerged as a pivotal standard designed to define how AI agents obtain, exchange, and act upon contextual data.</p>]]></description><link>https://shiftasia.com/community/model-context-protocol-for-ai-agent/</link><guid isPermaLink="false">6923b63018cce10001f0bbeb</guid><category><![CDATA[AI]]></category><dc:creator><![CDATA[TERRY]]></dc:creator><pubDate>Sat, 06 Dec 2025 03:26:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/11/Untitled-2025-10-21-1125.excalidraw.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/11/Untitled-2025-10-21-1125.excalidraw.png" alt="Understanding MCP: The Model Context Protocol for AI Agents"><p>In the rapidly evolving landscape of Large Language Models (LLMs), the ability to establish dependable communication between models and external systems has become a critical necessity. The <strong>Model Context Protocol (MCP)</strong> has emerged as a pivotal standard designed to define how AI agents obtain, exchange, and act upon contextual data. This article explores the fundamentals of MCP, its significance in the AI ecosystem, and how it is reshaping the future of multi-agent collaboration and system integration.</p><h2 id="what-is-mcp">What Is MCP?</h2><p>Model Context Protocol is a standardized, transport-agnostic way for AI agents to:</p><ul><li>Discover available tools, data sources, and capabilities</li><li>Request structured context</li><li>Invoke actions safely</li><li>Stream results and intermediate state</li></ul><p>It reduces ad&#x2011;hoc plugin contracts and replaces brittle prompt stuffing with explicit, typed exchanges.</p><h2 id="core-concepts">Core Concepts</h2><ul><li><strong>Resources</strong>: Read-only contextual objects (files, configs, embeddings).</li><li><strong>Tools</strong>: Executable operations with declared input/output schemas.</li><li><strong>Prompts </strong>/ <strong>Templates</strong>: Reusable contextual bundles served to models.</li><li><strong>Permissions</strong>: Fine-grained gating of tool/resource exposure.</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://shiftasia.com/community/content/images/2025/11/image-20.png" class="kg-image" alt="Understanding MCP: The Model Context Protocol for AI Agents" loading="lazy" width="2000" height="997" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/image-20.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/image-20.png 1000w, https://shiftasia.com/community/content/images/size/w1600/2025/11/image-20.png 1600w, https://shiftasia.com/community/content/images/size/w2400/2025/11/image-20.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Simple MCP server concepts</figcaption></figure><h2 id="high-level-flow">High-Level Flow</h2><ol><li>Client (LLM host) connects to MCP server.</li><li>Capability negotiation (tools, resources, prompts).</li><li>Model asks for context (resource listings, prompt retrieval).</li><li>Model invokes tool with structured arguments.</li><li>Server streams progress events.</li><li>Result packaged and appended to conversation context.</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://shiftasia.com/community/content/images/2025/11/image-22.png" class="kg-image" alt="Understanding MCP: The Model Context Protocol for AI Agents" loading="lazy" width="2000" height="690" srcset="https://shiftasia.com/community/content/images/size/w600/2025/11/image-22.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/11/image-22.png 1000w, https://shiftasia.com/community/content/images/size/w1600/2025/11/image-22.png 1600w, https://shiftasia.com/community/content/images/size/w2400/2025/11/image-22.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Agent interact to MCP server</figcaption></figure><p><strong>Example Interaction</strong></p><pre><code class="language-json">{
  &quot;type&quot;: &quot;tool.invoke&quot;,
  &quot;tool&quot;: &quot;searchLogs&quot;,
  &quot;arguments&quot;: { &quot;query&quot;: &quot;timeout error&quot;, &quot;limit&quot;: 25 },
  &quot;requestId&quot;: &quot;abc123&quot;
}</code></pre><pre><code class="language-json">{
  &quot;type&quot;: &quot;tool.result&quot;,
  &quot;requestId&quot;: &quot;abc123&quot;,
  &quot;status&quot;: &quot;ok&quot;,
  &quot;data&quot;: [
    { &quot;timestamp&quot;: &quot;...&quot;, &quot;line&quot;: &quot;TimeoutError: connection lost&quot; }
  ]
}</code></pre><h2 id="common-use-cases">Common Use Cases</h2><h4 id="a-software-development">a. Software Development</h4><p>Developers can use MCP-enabled AI agents to access code repositories, run tests, and deploy applications&#x2014;all through natural language commands.</p><h4 id="b-data-analysis">b. Data Analysis</h4><p>Analysts can leverage AI agents that connect to multiple data sources, perform complex queries, and generate insights without writing code.</p><h4 id="c-customer-support">c. Customer Support</h4><p>Support systems can use MCP to give AI agents access to knowledge bases, ticket systems, and customer data for more effective problem resolution.</p><h2 id="challenges">Challenges</h2><h4 id="a-versioning-of-tool-schemas">a. Versioning of Tool Schemas</h4><p>When tools evolve (new params, renamed fields, removed outputs), older clients may break or misinterpret results. Silent drift causes hallucinated usage or malformed invocations. Mixing schema versions inside one session amplifies ambiguity (e.g., cached prompt refers to deprecated argument). Without explicit semantic version tags and negotiation, rollback is painful.</p><h4 id="b-latency-for-large-resource-hydration">b. Latency for Large Resource Hydration</h4><p>Fetching large codebases, documents, or vector batches can stall the agent&#x2019;s reasoning loop, leading to timeouts or premature reasoning with incomplete context. Streaming helps, but naive full hydration wastes bandwidth and token budget.</p><h4 id="c-secure-sandboxing-of-side-effect-tools">c. Secure Sandboxing of Side-Effect Tools</h4><p>Tools that mutate state (deploy, write file, trigger pipeline) risk misuse if the model misinterprets instructions or an adversarial prompt causes unintended actions. Overly broad shell or network access turns an MCP server into a lateral movement surface.</p><h4 id="d-coordinating-multiple-concurrent-sessions">d. Coordinating Multiple Concurrent Sessions</h4><p>Several agents (planner, executor, reviewer) may compete for tool access, creating race conditions (one agent reads stale config another just changed). Without concurrency control, interleaved streams confuse attribution and degrade reasoning quality.</p><h2 id="best-practices">Best Practices</h2><ul><li>Keep tools granular and composable.</li><li>Provide lightweight summaries for large resources before full fetch.</li><li>Use streaming for long-running tasks.</li><li>Separate read vs. write capabilities explicitly.</li><li>Log every invocation with correlation IDs.</li></ul><h2 id="conclusion">Conclusion</h2><p>MCP formalizes how AI agents discover, request, and act on context, enabling secure, interoperable, and reliable integrations. Adopting it early positions teams for multi-agent collaboration and easier backend evolution. Start small: define one resource, one tool, validate the schema, then expand.</p><p><em><strong>Reference documents</strong></em></p><ul><li><a href="https://modelcontextprotocol.io/docs">https://modelcontextprotocol.io/docs</a></li><li><a href="https://www.anthropic.com/engineering/code-execution-with-mcp">https://www.anthropic.com/engineering/code-execution-with-mcp</a></li></ul>]]></content:encoded></item><item><title><![CDATA[How Worker Threads Bring Multithreading to Node.js]]></title><description><![CDATA[<p>One of the first things you learn about Node.js is the Golden Rule: <strong>&quot;Node.js is single-threaded.&quot;</strong></p><p>For 90% of web applications, this is a feature, not a bug. The Event Loop allows Node to handle thousands of concurrent I/O connections (like database queries or API</p>]]></description><link>https://shiftasia.com/community/how-worker-threads-bring-multithreading-to-node-js/</link><guid isPermaLink="false">692e5b5718cce10001f0cd5b</guid><category><![CDATA[back-end]]></category><dc:creator><![CDATA[Hayes Ly]]></dc:creator><pubDate>Sat, 06 Dec 2025 03:21:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/thumbworker.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/12/thumbworker.png" alt="How Worker Threads Bring Multithreading to Node.js"><p>One of the first things you learn about Node.js is the Golden Rule: <strong>&quot;Node.js is single-threaded.&quot;</strong></p><p>For 90% of web applications, this is a feature, not a bug. The Event Loop allows Node to handle thousands of concurrent I/O connections (like database queries or API calls) without the overhead of creating threads.</p><p><strong>But there is a catch.</strong></p><p>Because there is only one thread, if you run a heavy CPU task (like image processing, video compression, or complex implementation of cryptography), you block that single thread. Your entire server freezes. No one else can log in, no APIs respond. The application effectively dies until that calculation finishes.</p><p>Enter <strong>Worker Threads</strong>.</p><p>Introduced as a stable feature in Node v12, Worker Threads allow you to break the &quot;Single-Threaded&quot; rule and execute JavaScript in parallel background threads.</p><h2 id="the-chef-analogy"><strong>The &quot;Chef&quot; Analogy</strong></h2><p>To understand why we need Workers, let&apos;s look at a restaurant kitchen.</p><ol><li><strong>Standard Node.js (The Main Thread):</strong> You have <strong>one Chef</strong>. This Chef is a master multitasker. He takes an order, puts a pizza in the oven, and immediately takes the next order. He doesn&apos;t wait for the pizza to bake (Async I/O). This is fast and efficient.</li><li><strong>The Problem (CPU Blocking):</strong> Suddenly, a customer orders a &quot;Hand-Carved Ice Sculpture.&quot; The Chef has to stop taking orders and spend 20 minutes chiseling ice. The restaurant halts. The pizza in the oven burns. Customers leave.</li><li><strong>The Solution (Worker Threads):</strong> You hire a <strong>Sous-Chef</strong> (a Worker). When the Ice Sculpture order comes in, the Head Chef passes the ticket to the Sous-Chef in the back room. The Head Chef goes back to taking orders instantly, while the Sous-Chef works in parallel.</li></ol><h2 id="how-worker-threads-work-under-the-hood"><strong>How Worker Threads Work Under the Hood</strong></h2><p>Unlike the cluster module (which spawns entirely new Node.js <strong>processes</strong>), Worker Threads create new <strong>threads</strong> within the <em>same</em> process.</p><p>Here is the architecture:</p><h3 id="1-isolated-v8-engines"><strong>1. Isolated V8 Engines</strong></h3><p>Each Worker Thread gets its own instance of the V8 engine and its own Event Loop. This means:</p><ul><li>Variables are <strong>not</strong> shared automatically. A global variable in the Main Thread does not exist in the Worker Thread.</li><li>If a Worker crashes, it doesn&apos;t necessarily kill the Main Thread.</li></ul><h3 id="2-communication-via-messaging"><strong>2. Communication via Messaging</strong></h3><p>Since scopes are isolated, the Main Thread and the Worker communicate by passing messages back and forth, similar to how a frontend talks to a Web Worker.</p><ul><li><strong>Main:</strong> &quot;Here is the data. Start working.&quot; (worker.postMessage())</li><li><strong>Worker:</strong> &quot;I received it. Processing...&quot; (parentPort.on(&apos;message&apos;))</li><li><strong>Worker:</strong> &quot;I am done. Here is the result.&quot; (parentPort.postMessage())</li></ul><h3 id="3-shared-memory-the-superpower"><strong>3. Shared Memory (The Superpower)</strong></h3><p>This is where Workers shine over Child Processes. Workers can share memory using SharedArrayBuffer. This allows the Main Thread and the Worker to read/write to the same chunk of memory without the expensive cost of serializing data (converting objects to text) to send it back and forth.</p><figure class="kg-card kg-image-card"><img src="https://shiftasia.com/community/content/images/2025/12/worker.jpg" class="kg-image" alt="How Worker Threads Bring Multithreading to Node.js" loading="lazy" width="2000" height="1067" srcset="https://shiftasia.com/community/content/images/size/w600/2025/12/worker.jpg 600w, https://shiftasia.com/community/content/images/size/w1000/2025/12/worker.jpg 1000w, https://shiftasia.com/community/content/images/size/w1600/2025/12/worker.jpg 1600w, https://shiftasia.com/community/content/images/2025/12/worker.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="a-simple-example">A Simple Example</h2><p>Imagine calculating the Fibonacci sequence for a large number. On the main thread, this would freeze your server. Here is how it looks with a Worker.</p><!--kg-card-begin: markdown--><pre><code class="language-js">// main.js
const { Worker } = require(&apos;worker_threads&apos;);

function runService(workerData) {
  return new Promise((resolve, reject) =&gt; {
    // Spin up a new worker
    const worker = new Worker(&apos;./worker.js&apos;, { workerData });
    
    // Listen for the result
    worker.on(&apos;message&apos;, resolve);
    worker.on(&apos;error&apos;, reject);
    worker.on(&apos;exit&apos;, (code) =&gt; {
      if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
    });
  });
}

async function run() {
  console.log(&quot;Main thread is free to do other things...&quot;);
  const result = await runService(40); // Calculate Fib(40)
  console.log(&quot;Result from worker:&quot;, result);
}

run();

</code></pre>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><pre><code class="language-js">// worker.js
const { workerData, parentPort } = require(&apos;worker_threads&apos;);

// A CPU-heavy function
function fibonacci(n) {
  if (n &lt; 2) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

// Do the work
const result = fibonacci(workerData);

// Send result back to main thread
parentPort.postMessage(result);

</code></pre>
<!--kg-card-end: markdown--><h2 id="when-to-use-workers">When to Use Workers</h2><p>It is tempting to throw everything into a Worker Thread to make it &quot;faster,&quot; but that often backfires. Creating a Worker is expensive (it has to boot up a V8 instance).</p><h3 id="%E2%9D%8C-do-not-use-workers-for-io"><strong>&#x274C; Do NOT use Workers for I/O</strong></h3><p>Don&apos;t use Workers for database queries, HTTP requests, or file reading.</p><ul><li><strong>Why?</strong> Node.js already does this efficiently in the background using C++ threads (via libuv). Wrapping an async DB call in a Worker Thread just adds overhead for no gain.</li></ul><h3 id="%E2%9C%85-do-use-workers-for-cpu-tasks"><strong>&#x2705; DO use Workers for CPU Tasks</strong></h3><p>Use Workers when you have to process data synchronously.</p><ul><li><strong>Image Processing:</strong> Resizing, cropping, or filtering images (e.g., sharp library).</li><li><strong>Video Compression:</strong> Transcoding video files.</li><li><strong>Cryptography:</strong> Generating massive RSA keys or hashing thousands of passwords.</li><li><strong>Data Parsing:</strong> Parsing a 500MB JSON or CSV file.</li></ul><h2 id="conclusion"><strong>Conclusion</strong></h2><p>Node.js is no longer &quot;just&quot; single-threaded.</p><p>While the Event Loop remains the heart of Node.js for handling high-concurrency I/O, <strong>Worker Threads</strong> give you the muscle to handle heavy computation.</p><p>By offloading heavy math and parsing to background threads, you ensure your Main Thread stays where it belongs: handling incoming requests at lightning speed.</p><h2 id="references">References</h2><ul><li><a href="https://nodesource.com/blog/worker-threads-nodejs">https://nodesource.com/blog/worker-threads-nodejs</a></li><li><a href="https://medium.com/@manikmudholkar831995/worker-threads-multitasking-in-nodejs-6028cdf35e9d">https://medium.com/@manikmudholkar831995/worker-threads-multitasking-in-nodejs-6028cdf35e9d</a></li><li><a href="https://www.scaler.com/topics/nodejs/worker-threads-in-node-js/">https://www.scaler.com/topics/nodejs/worker-threads-in-node-js/</a></li></ul><p><br></p>]]></content:encoded></item><item><title><![CDATA[How to Write Detailed Design for APIs with Create, Update, Delete Functionality]]></title><description><![CDATA[<p>After mastering how to design search APIs (see the previous article), it&#x2019;s time to dive into the family of &#x201C;write&#x201D; APIs &#x2014; create, update, and delete. These APIs directly affect system data, so their design must be careful and rule-driven.</p><h2 id="structure-of-detailed-design-for-create-update-delete-apis">Structure of Detailed Design for Create,</h2>]]></description><link>https://shiftasia.com/community/how-to-write-detailed-design-for-apis-with-search-functionality-2/</link><guid isPermaLink="false">69310f4418cce10001f0ceb8</guid><category><![CDATA[back-end]]></category><category><![CDATA[WEB]]></category><dc:creator><![CDATA[VIOLET Dang]]></dc:creator><pubDate>Fri, 05 Dec 2025 06:58:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/3.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/12/3.png" alt="How to Write Detailed Design for APIs with Create, Update, Delete Functionality"><p>After mastering how to design search APIs (see the previous article), it&#x2019;s time to dive into the family of &#x201C;write&#x201D; APIs &#x2014; create, update, and delete. These APIs directly affect system data, so their design must be careful and rule-driven.</p><h2 id="structure-of-detailed-design-for-create-update-delete-apis">Structure of Detailed Design for Create, Update, Delete APIs</h2><h3 id="1-api-name">1. API Name</h3><p>As with search APIs, naming for write APIs should be concise, consistent, and clear. Avoid verbose names like &#x201C;API to add a new product&#x201D; or &#x201C;API to delete a user.&#x201D; Use these conventions:</p><ul><li>Standard create: [Entity] + Create/Add<br>Example: `userCreate` &#x2014; Create a new user</li><li>Standard update: [Entity] + Update/Edit<br>Example: `productUpdate` &#x2014; Update product information</li><li>Standard delete: [Entity] + Delete<br>Example: `orderDelete` &#x2014; Delete an order</li><li>Partial update: [Entity] + [Action]<br>Examples:<br> &#xA0; &#xA0;- `orderUpdateStatus` &#x2014; Update order status<br> &#xA0; &#xA0;- `userUnblock` &#x2014; Unblock a user</li><li>Create/update/delete by a foreign key (parent ID)<br>Example: `productUpdateByShopId` &#x2014; Update product by shop ID (often includes constraints)</li><li>Bulk create multiple records: [Entity] + BulkCreate<br>Example: `shopBulkCreate` &#x2014; Create multiple shops at once</li></ul><p>With this convention, the team can infer functionality from the API name alone &#x2014; no extra explanation needed.</p><h3 id="2-http-method">2. HTTP Method</h3><p>Write APIs typically use these methods:</p><!--kg-card-begin: html--><table border="1">
  <thead>
    <tr>
      <th>Function</th>
      <th>Method</th>
      <th>When to use</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="padding: 2px">Create</td>
      <td style="padding: 2px">POST</td>
      <td style="padding: 2px">When adding a new record to the system</td>
    </tr>
    <tr>
      <td style="padding: 2px">Update (full)</td>
      <td style="padding: 2px">PUT</td>
      <td style="padding: 2px">When replacing the entire record</td>
    </tr>
    <tr>
      <td style="padding: 2px">Partial update</td>
      <td style="padding: 2px">PATCH</td>
      <td style="padding: 2px">When updating part of a record</td>
    </tr>
    <tr>
      <td style="padding: 2px">Delete</td>
      <td style="padding: 2px">DELETE</td>
      <td style="padding: 2px">When removing a record from the system</td>
    </tr>
  </tbody>
</table><!--kg-card-end: html--><p><strong>Why these methods and not others?</strong></p><p>Technically, nothing stops you from using POST to update or PATCH to create. However, choosing the method that matches the intent makes your API easier to manage, read, maintain, and it adheres to RESTful conventions. Each method carries meaning, helping readers of docs or code understand the API&#x2019;s purpose without extra commentary. When the team sticks to these rules, collaboration and development go much smoother.</p><p><strong>Method breakdown</strong></p><ul><li>POST:<br> &#xA0;- Used to create a new resource. The client sends data in the request body; the server creates the record and returns it (usually with an ID). &#x2192; Hence POST is typically for creation because it generates a new resource.<br> &#xA0;- Can be used for single or bulk creation, or to create a child resource under a parent (e.g., create a product for a shop).<br> &#xA0;- Some systems use POST for partial updates, but this is discouraged because it&#x2019;s confusing.</li><li>PUT:<br> &#xA0;- Used to replace a record entirely. The client usually sends all fields, including unchanged ones.<br> &#xA0;- PUT is &#x201C;replace&#x201D; semantics &#x2014; missing fields may be removed or set to default (system-dependent).<br> &#xA0;- Use PUT when you want the record&#x2019;s state to match exactly what&#x2019;s sent.</li><li>PATCH:<br> &#xA0;- Used to update part of a record &#x2014; only fields sent are changed; others remain.<br> &#xA0;- Good for flexible updates, e.g., changing status or tweaking one field without sending the full payload.<br> &#xA0;- Helps save bandwidth and avoids unintended overwrites.</li><li>DELETE:<br> &#xA0;- Used to remove a record. The client typically sends the record identifier (ID).<br> &#xA0;- Some systems implement soft delete, marking records as deleted rather than physically removing them. The DELETE endpoint remains, but the deletion logic must be documented.</li></ul><p><strong>Practical notes</strong></p><ul><li>If deletion requires confirmation (e.g., `confirm=true`), document it clearly</li><li>For multi-record updates, you can use PUT/PATCH with an array of IDs or a dedicated endpoint like `/products/bulk-update`.</li><li>Don&#x2019;t overuse POST for all write operations &#x2014; follow REST to keep your API extensible, maintainable, and compatible with tooling and documentation.</li><li>Legacy or third-party integrations may force POST for update/delete. If so, document the reason clearly to avoid confusion.</li></ul><p>In short, picking the right HTTP method is not just theoretical &#x2014; it improves development, maintenance, testing, and integration. If you have exceptions, note them clearly in the design so everyone aligns.</p><h3 id="3-uri">3. URI</h3><p>URI design for create, update, delete is similar to search APIs. If needed, revisit the previous article&#x2019;s URI principles. Here are practical tips for this group:</p><ul><li>For operations on a specific resource (e.g., update or delete a product), place the resource ID in the URI path. It should be immediately clear what you&#x2019;re doing and to which ID.<br>Examples:<br> &#xA0; &#xA0;- `PUT /products/123` &#x2014; Update product with ID 123<br> &#xA0; &#xA0;- `DELETE /products/123` &#x2014; Delete product with ID 123</li><li>For child resources scoped by a parent foreign key, include the parent ID in the path to clarify the context. This makes documentation readable and the business flow easier to grasp.<br>Example: `POST /shops/{shop_id}/products` &#x2192; `POST /shops/5/products` &#x2014; Create/update/delete a product for shop ID 5</li><li>For bulk operations (bulk update, bulk delete), don&#x2019;t cram IDs into the path. Long, comma-separated or special-character-separated lists make the URI unwieldy and parsing error-prone. Instead, send the list via query parameters or the request body. It&#x2019;s cleaner, more extensible, and safer for backend parsing.</li><li>A common pattern is to share the same URI for read, update, and delete &#x2014; differing only by HTTP method. This is normal and increases consistency.<br>Examples:<br> &#xA0; &#xA0;- `GET /products/{product_id}` &#x2014; Get product details<br> &#xA0; &#xA0;- `PUT /products/{product_id}` &#x2014; Update product details<br> &#xA0; &#xA0;- `DELETE /products/{product_id}` &#x2014; Delete product</li></ul><p>Design URIs so that, at a glance, you know what the API does, on which resource, and within what scope. Don&#x2019;t hesitate to reuse search API URI examples &#x2014; the core principles are clarity, consistency, and ease of team communication.</p><h3 id="4-authentication-and-authorization">4. Authentication and Authorization</h3><p>This was covered in detail previously, so revisit that article if needed.</p><p>One extremely important point for write APIs that you must never gloss over: <strong>Insecure Direct Object Reference (IDOR)</strong>. In search or read-only APIs, IDOR primarily leaks data &#x2014; users can view others&#x2019; information. In create/update/delete, the consequences are much more severe: attackers can modify, delete, or even take over others&#x2019; data simply by changing IDs in requests.</p><p>For example, if an API allows order status updates and only checks the order ID provided by the client, user A might update user B&#x2019;s order by swapping IDs. This leads to unintended modifications/deletions and damages trust. Always check ownership and permissions rigorously &#x2014; never trust IDs from the client alone.</p><h3 id="5-input-parameters">5. Input Parameters</h3><p>Unlike search APIs, create/update/delete APIs usually have fewer complex URI or query parameters. These typically just identify the resource to operate on (e.g., product ID, user ID).</p><p>Most of the data needed to create, update, or delete is sent via the request body. Why?</p><ul><li>First, request body is more secure, especially for sensitive fields (passwords, personal info). URLs are easily logged by proxies, browsers, or intermediaries.</li><li>Second, payloads are often large and structured &#x2014; query strings have length limits (often ~2048 chars) and can be truncated.</li><li>Third, the body supports various data types, such as images, audio, CSV, Excel. Query parameters cannot do this. For file upload or binary payloads, only the body (`multipart/form-data` or binary) suffices. This is crucial for create/update APIs involving attachments.</li><li>Fourth, body data makes backend validation and extensibility easier. You can define a body schema (JSON Schema, Joi, Yup, etc.), declare validation rules, and let the framework enforce them before business logic. Adding fields later is simple &#x2014; update the schema without changing the path or query string.</li></ul><p><strong>&#x25C6; Common request body types</strong></p><p>Below are the typical body formats for write APIs:</p><ul><li><strong>application/json: </strong>The most common for structured create/update operations.<br>Example:</li></ul><pre><code class="language-bash">POST /products
Content-Type: application/json
{
  &quot;name&quot;: &quot;iPhone 17 Pro Max 512GB&quot;,
  &quot;price&quot;: 40000000,
  &quot;description&quot;: &quot;Apple&#x2019;s latest product&quot;,
  &quot;in_stock&quot;: true
}</code></pre><ul><li><strong>multipart/form-data:</strong> Used when sending files (images, audio, documents) alongside text fields. Each part is separate; backend receives both file(s) and metadata.<br>Example:</li></ul><pre><code class="language-bash">POST /products
Content-Type: multipart/form-data
name: iPhone 15
price: 25000000
image: [image file]</code></pre><ul><li><strong>application/x-www-form-urlencoded: </strong>Common for simple forms; data is key=value. Suitable for endpoints with few fields and no files.<br>Example:</li></ul><pre><code class="language-bash">POST /login
Content-Type: application/x-www-form-urlencoded
username=abc&amp;password=xy</code></pre><p>The above are the three most common ways to send data; there are also less common types such as:</p><ul><li><strong>text/plain:</strong> Plain text payloads for very simple data.</li><li><strong>application/xml:</strong> XML payloads for legacy systems or specific partner integrations.</li><li><strong>application/octet-stream: </strong>Binary data such as zip/exe or specially encoded content.</li><li><strong>application/pdf, image/png, image/jpeg, audio/mpeg, video/mp4...:</strong> Direct file uploads where the payload itself is the file.</li><li><strong>application/csv, application/vnd.ms-excel: </strong>Tabular data uploads for bulk import.</li></ul><p><strong>&#x25C6; Why not use `multipart/form-data` for everything?</strong></p><p>You might wonder: &#x201C;Why not always use `multipart/form-data` since it handles files and text?&#x201D; Sounds convenient, but it&#x2019;s not ideal:</p><ul><li>If the API only receives text/JSON, `multipart/form-data` complicates things:<br> &#xA0;- Modern frameworks provide strong schema/type/value validation for JSON. With multipart, you lose these conveniences and must manually parse and validate fields.<br> &#xA0;- Frontend can send JSON with a simple function call; multipart requires building `FormData`, appending fields, handling files.<br> &#xA0;- Backend must parse parts and cannot leverage JSON validators effectively.</li><li>`multipart/form-data` adds boundaries, headers, and encoding, making requests heavier than plain JSON. If you&#x2019;re sending only text, JSON saves bandwidth and reduces server load.</li><li>Documentation/testing tools (Swagger/OpenAPI, CI/CD integrations) default to application/json for write APIs. Using multipart everywhere complicates docs and automation and confuses teams.</li></ul><p>Practical examples:</p><ul><li>Create product with image: use `multipart/form-data` for file + metadata.</li><li>Create product without files: use `application/json` &#x2014; simpler and more robust.</li></ul><p>Bottom line: choose the body type that fits the API&#x2019;s purpose. Use multipart for file uploads; use JSON for text-only payloads. This improves validation, maintainability, performance, and integration.</p><h3 id="6-data-validation">6. Data Validation</h3><p>Unlike search APIs, write APIs must enforce multiple layers of validation &#x2014; tightly &#x2014; to protect the system from attacks and business errors. For search, validation mainly prevents resource abuse (e.g., huge limits). For write, validation is the &#x201C;security fence&#x201D; guarding data from corruption, loss, and exploitation.</p><p><strong>&#x25C6; Mandatory validations for write APIs</strong></p><p><strong>&#x25C7; Security hardening:</strong></p><ul><li><strong>Block SQL Injection: </strong>Always sanitize client inputs. Disallow dangerous characters/patterns like single/double quotes, semicolons, SQL comments (`--`), or keywords like SELECT/INSERT/DROP/UNION. Prefer parameterized queries/ORMs; never string-concatenate SQL.</li><li><strong>Block XSS: </strong>Strip dangerous HTML/script patterns such as `&lt;script&gt;`, `javascript:`, `onload`, `onerror` in all user-provided fields, especially descriptions/notes. Use sanitize libraries or escape HTML before storing/rendering.</li><li><strong>Blacklist attack patterns:</strong> Maintain known-dangerous patterns (command strings, malware payloads, special characters) and reject inputs that match. Use security libraries or custom rules.</li><li><strong>Validate uploaded files:</strong> Check MIME type, extension, and actual content. Allow only safe types (jpg/png/pdf...), reject dangerous types (.exe/.js/.bat/.sh...). Also verify file size and enforce limits to prevent resource exhaustion.</li></ul><p><strong>&#x25C7; Authorization checks:</strong> Define exactly which user roles may perform which actions under which business states. Rule of thumb: only allow the right user, right role, right state to perform the right action; reject everything else.</p><p>Example for order status updates:<br>- Sales staff can set status to &#x201C;awaiting payment confirmation&#x201D;.<br>- Warehouse staff can set to &#x201C;shipped from warehouse&#x201D; or &#x201C;returned to warehouse&#x201D;.<br>- Accounting can set to &#x201C;payment confirmed&#x201D;.<br>- Customer can set to &#x201C;order canceled&#x201D;.<br>- Admin may have broader permissions (if business permits).<br>- Any mismatch (e.g., warehouse confirming payment) must be rejected.</p><p><strong>&#x25C7; Required fields:</strong> Fields that are non-nullable/required in the database must be required by create/update APIs as well. Required means the client must send the field, it must have a value, and it must not be an empty string &apos;&apos;.</p><ul><li><strong>Create APIs:</strong> If the database has no default, the API must require the field and reject empty &apos;&apos;. If the database has a default and you want to always store that default when creating, do not accept the field from the client (even if sent). This avoids security holes, e.g., creating an order with initial status set to cancel.</li><li><strong>Update APIs:</strong> Data already exists. If a field may be edited, accept it; otherwise block it. Do not allow updating fields to empty &apos;&apos;.</li></ul><p><strong>&#x25C7; Type validation:</strong> Every field must match its declared type (integer, float/decimal, string, boolean, array, object, date, enum&#x2026;) and this must align with the database schema. If the type is wrong, return an error &#x2014; do not auto-coerce or ignore.</p><ul><li><strong>Integer: </strong>Only integers; no floats, strings, or special characters.<br>Examples:<br> &#xA0; &#xA0;- 1, 100, -5 are valid<br> &#xA0; &#xA0;- 1.5, &quot;abc&quot; are invalid</li><li><strong>Float/double/decimal: </strong>Accept floats or integers.<br>Examples:<br> &#xA0; &#xA0;- 1.5, 100.0, -3 are valid<br> &#xA0; &#xA0;- &quot;abc&quot; are invalid</li><li><strong>String:</strong> Only character strings.<br>Examples:<br> &#xA0; &#xA0;- &quot;iPhone&quot;, &quot;abc123&quot; are valid<br> &#xA0; &#xA0;- 123 are invalid</li><li><strong>Boolean:</strong> Accept true/false or 1/0 depending on the system.<br>Examples:<br> &#xA0; &#xA0;- true, false, 1, 0 are valid<br> &#xA0; &#xA0;- &quot;yes&quot;, &quot;no&quot; are invalid</li><li><strong>Date/datetime/timestamp: </strong>Strings in a valid format (ISO 8601, yyyy-MM-dd, yyyy-MM-dd HH:mm:ss...).<br>Examples:<br> &#xA0; &#xA0;- &quot;2025-10-14&quot;, &quot;2025-10-14T10:00:00Z&quot; are valid<br> &#xA0; &#xA0;- &quot;2025/10/14&quot;, &quot;14/10/2025&quot;, &quot;abc&quot; are invalid</li><li><strong>Enum:</strong> Values must be within the allowed set.<br>Examples:<br> &#xA0; &#xA0;- Order status: only &quot;pending&quot;, &quot;confirmed&quot;, &quot;cancel&quot;<br> &#xA0; &#xA0;- Others are invalid.</li><li><strong>Array:</strong> Must be a list of elements of consistent types; validate count and element types.<br>Examples:<br> &#xA0; &#xA0;- [1,2,3], [&quot;a&quot;,&quot;b&quot;] are valid<br> &#xA0; &#xA0;- &quot;1,2,3&quot;, null are invalid</li><li><strong>Object:</strong> Must match the designed structure; nested fields must also be valid.<br>Examples:<br> &#xA0; &#xA0;- {&quot;name&quot;:&quot;A&quot;,&quot;price&quot;:100} is valid<br> &#xA0; &#xA0;- &quot;{name:A}&quot;, null are invalid</li></ul><p><strong>&#x25C7; Value validation:</strong></p><ul><li>Examples:<br> &#xA0; &#xA0;- Quantity must be between 1 and 100; &lt;=0 or &gt;100 is invalid.<br> &#xA0; &#xA0;- Date must be today or future; past dates are invalid.</li></ul><p><strong>&#x25C7; Length, pattern, format:</strong></p><ul><li>Examples: product name &lt;= 255 chars, email format valid, phone number matches pattern.</li><li>Don&#x2019;t forget file checks: if API allows file uploads, validate type, count, and size. Clarify whether limits apply per request, per resource ID, or per file.</li></ul><p><strong>&#x25C7; Uniqueness checks:</strong></p><ul><li>Examples: email, username, product code must be unique and not duplicate existing records.</li><li>Consider whether to include soft-deleted records in uniqueness checks. Some systems ignore soft-deleted records &#x2014; e.g., if an account with username &quot;test&quot; was soft-deleted, creating a new account with &quot;test&quot; may be allowed.</li></ul><p><strong>&#x25C7; Business logic validation: </strong>e.g., order status may only transition from &quot;pending&quot; to &quot;confirmed&quot;, not backwards.</p><p><strong>&#x25C6; Why is validation critical for write APIs?</strong></p><p>If you skip or loosen validation for write endpoints, you risk:</p><ul><li>Security vulnerabilities: SQLi, XSS, malicious uploads.<br>Examples:<br> &#xA0;- Without input sanitization, a client could set product name to `&apos;; DROP TABLE products; --` and attempt SQL injection, wiping the table.<br> &#xA0;- Without script blocking, a client could set a description to `&lt;script&gt;alert(&apos;XSS&apos;)&lt;/script&gt;`, attacking users viewing it on the web UI.<br> &#xA0;- Without file type checks, attackers could upload `.exe` or scripts, potentially compromising the server.</li><li>Unauthorized actions: users performing operations beyond their roles.<br>Example: warehouse staff setting order status to &#x201C;paid&#x201D;.</li><li>Bad data and broken business processes.<br>Example: if types aren&#x2019;t checked, sending price as &quot;abc&quot; may crash the system or corrupt the DB.</li><li>Duplicates and inconsistency, hard to audit and maintain.<br>Examples:<br> &#xA0;- Multiple users with the same email/username breaks login, notifications, and role assignments.<br> &#xA0;- Duplicate product codes cause confusion in inventory, invoicing, or external integrations.<br> &#xA0;- Invalid status transitions or unsynchronized multi-table writes lead to retrieval/reporting errors.</li></ul><p>In short, validation for write APIs is not &quot;nice-to-have&quot; &#x2014; it&#x2019;s mandatory. Invest in designing, enforcing, and documenting validation rules to protect your system, data, and product reputation.</p><h3 id="7-data-persistence">7. Data Persistence</h3><p>This is the heart of create/update/delete APIs. Bad or incomplete writes cause bad data and downstream pain. Document thoroughly:</p><ul><li>Which tables/columns to insert/update/delete.</li><li>For create/update:<br> &#xA0;- Specify stored values (omit when using DB defaults).<br> &#xA0;- If branching logic results in different storage semantics, document each branch clearly.<br> &#xA0;- If files are uploaded, specify storage location, naming conventions, and any file metadata to persist (original name, size&#x2026;).<br> &#xA0;- For date/time/datetime, state the timezone explicitly.<br> &#xA0;- Don&#x2019;t forget related tables! If writing to `orders`, should you also write to `order_details`? If writing to `products`, do you also write to `product_suppliers`?</li><li>For delete:<br> &#xA0;- Hard delete or soft delete?<br> &#xA0;- Whether to delete dependent records (foreign-key-bound tables).<br> &#xA0;- If records have files stored elsewhere, whether to delete corresponding files.</li></ul><h3 id="8-output-parameters">8. Output Parameters</h3><p>Unlike search APIs, write APIs focus on writing, so output guidelines are simpler:</p><ul><li>Return the minimal information necessary. Typically `id` (and optionally `version`/ETag) so the client can confirm and proceed. For detailed views, call the corresponding GET. Returning full objects from multiple endpoints leads to divergent contracts and higher maintenance costs.</li><li>Standardize HTTP status codes for each case so frontend messaging is consistent. For example: `201 Created` for create, `204 No Content` for update/delete when no body is needed.</li></ul><h2 id="sample-createupdatedelete-apis-detailed-design">Sample Create/Update/Delete APIs Detailed Design</h2><p>You can view and download the template (API Blueprint) to use as a standard frame for writing detailed designs for search APIs [here](<a href="https://github.com/sa-violetdang/advanced-api-documentation">https://github.com/sa-violetdang/advanced-api-documentation</a>).</p><h2 id="conclusion">Conclusion</h2><p>From naming, HTTP methods, URIs, security, validation, to storage and responses &#x2014; you now have a solid framework to design clean, extensible, low-tech-debt write APIs.</p><p>The key to write APIs isn&#x2019;t a verbose response but discipline: perform the write correctly, respond minimally, and use standard status codes so the client understands immediately without extra ceremony. The less extraneous data you return, the more stable the contract and the lower the maintenance cost.</p><h3 id="key-takeaways">Key Takeaways</h3><ol><li><strong>Start minimal, expand when needed:</strong> Prefer `204 No Content` for update/delete and return only `id` on create. If required, add minimal `version`/ETag or `links.self` &#x2014; avoid returning full objects.</li><li><strong>Consistent contracts:</strong> Names, URIs, methods reflect semantics; status codes clear (`201/204/400/404/409`). Use stable time/id formats to simplify integration and testing.</li><li><strong>Validation is the safety fence:</strong> Security (SQLi/XSS/files), authorization, types, uniqueness, and business rules. Document once and enforce across the team.</li><li><strong>Principled persistence:</strong> Transactions, write order, hard/soft delete, table relations, file handling. Document semantics to avoid bad data and painful rollbacks.</li><li><strong>Advanced features when needed:</strong> Add idempotency for POST, concurrency via `ETag/If-Match`, observability with `requestId`/timestamp, and support bulk/async with clear contracts (partial success, `202 Accepted`).</li></ol><p>Above all, remember: good design reduces guesswork for API consumers (FE/BE). Every line in your docs should cut communication errors and speed development. Keep responses lean and contracts clear &#x2014; reads belong to GET &#x2014; that&#x2019;s how your system stays robust over time.</p>]]></content:encoded></item><item><title><![CDATA[CSS Priority Order: How the Browser Decides Which Style Wins]]></title><description><![CDATA[<p>Have you ever wondered why some of your CSS rules don&#x2019;t apply even though the code looks perfectly correct?<br>This usually comes down to one thing: <strong>CSS specificity</strong> &#x2014; a critical concept that many developers overlook.</p><h2 id="1-a-quick-story">1. <strong>A Quick Story</strong></h2><p>Today a developer on my team asked:<br><em>&quot;</em></p>]]></description><link>https://shiftasia.com/community/css-specificity-the-secret-behind-non-working-css-rules/</link><guid isPermaLink="false">68e8b5d018cce10001f0a9af</guid><category><![CDATA[front-end]]></category><dc:creator><![CDATA[Thiago]]></dc:creator><pubDate>Fri, 05 Dec 2025 04:35:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/11/Specificity_in_CSS-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/11/Specificity_in_CSS-1.png" alt="CSS Priority Order: How the Browser Decides Which Style Wins"><p>Have you ever wondered why some of your CSS rules don&#x2019;t apply even though the code looks perfectly correct?<br>This usually comes down to one thing: <strong>CSS specificity</strong> &#x2014; a critical concept that many developers overlook.</p><h2 id="1-a-quick-story">1. <strong>A Quick Story</strong></h2><p>Today a developer on my team asked:<br><em>&quot;Why isn&apos;t my CSS working now? When I add it, </em><code><em>!important</em></code><em> it works.&quot;</em></p><!--kg-card-begin: markdown--><pre><code class="language-css">.button { 
  background-color: blue !important;
}

#header .nav .button {
  background-color: red;
}
</code></pre>
<!--kg-card-end: markdown--><p>This is a perfect example of why learning the relationship between <code>!important</code> and specificity is so important for every front-end developer.</p><h2 id="2-how-important-works">2. How !important works</h2><p><code>!important</code> is the nuclear option of CSS. Use it with caution.</p><!--kg-card-begin: markdown--><p>Here are the rules:</p>
<ol>
<li><code>!important</code> beats all normal specificity, even ID selectors.</li>
<li>If two <code>!important</code> rules conflict, specificity is recalculated normally to determine the winner.</li>
<li>Inline <code>!important</code> has higher priority than stylesheet <code>!important</code>.</li>
<li>Relying on <code>!important</code> too often is a sign of deeper CSS architecture issues.</li>
</ol>
<!--kg-card-end: markdown--><h2 id="3-what-is-css-specificity">3. What is CSS Specificity?</h2><p>CSS Specificity is the mechanism browsers use to decide which CSS rule will be applied when multiple rules target the same element.</p><p>Think of it like a competition between selectors. The more &quot;powerful&quot; the selector, the higher its score &#x2014; and the more likely its styles will apply.</p><h2 id="4-specificity-calculation">4. Specificity Calculation</h2><p>Specificity is commonly represented as a <strong>four-part value</strong>: (a, b, c, d)<br><strong>a</strong> &#x2192; Inline styles<br><strong>b</strong> &#x2192; ID selectors (#header)<br><strong>c</strong> &#x2192; Class, attribute, and pseudo-class selectors (.btn, [type=&quot;text&quot;], :hover)<br><strong>d</strong> &#x2192; Element and pseudo-element selectors (div, h1, ::before)</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>Selector Type</th>
<th>Specificity Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Inline style</td>
<td>(1,0,0,0)</td>
</tr>
<tr>
<td>ID selector (#id)</td>
<td>(0,1,0,0)</td>
</tr>
<tr>
<td>Class (.class), attribute ([type=&quot;text&quot;]), pseudo-class (:hover)</td>
<td>(0,0,1,0)</td>
</tr>
<tr>
<td>Element (div, h1, p), pseudo-element (::before)</td>
<td>(0,0,0,1)</td>
</tr>
<tr>
<td>!important</td>
<td>Overrides all</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>To make comparison easier, developers often map specificity to a scoring system:<br><strong>a &#xD7; 1000 + b &#xD7; 100 + c &#xD7; 10 + d</strong></p><h2 id="5-specificity-in-action">5. Specificity in Action</h2><p>Let&#x2019;s walk through a set of CSS rules and see which one wins:</p><!--kg-card-begin: markdown--><pre><code class="language-css">/* Rule 1: (0, 0, 0, 1) = 1 point */
button { 
  background: gray;
  padding: 10px;
}

/* Rule 2: (0, 0, 1, 0) = 10 points */
.btn { 
  background: blue;
  border-radius: 4px;
}

/* Rule 3: (0, 0, 2, 0) = 20 points */
.btn.buy-now { 
  background: green;
  font-weight: bold;
}

/* Rule 4: (0, 0, 2, 1) = 21 points */
.product-card button.btn { 
  background: orange;
}

/* Rule 5: (0, 1, 2, 1) = 121 points - WINS! */
#product-page .product-card button.btn { 
  background: red;
  color: white;
}

/* Rule 6: (0, 0, 1, 0) = 10 points */
[data-category=&quot;electronics&quot;] { 
  background: purple;
}
</code></pre>
<!--kg-card-end: markdown--><p>Here, <strong>Rule 5</strong> wins because the ID selector gives it the highest specificity.</p><h2 id="6-conclusion">6. Conclusion</h2><!--kg-card-begin: markdown--><p>To write maintainable and conflict-free CSS, remember:</p>
<ul>
<li>Prefer <strong>classes over IDs</strong> &#x2014; they scale better.</li>
<li>Avoid unnecessary nesting &#x2014; it increases specificity without real benefit.</li>
<li>Use <code>!important</code> only when absolutely necessary.</li>
<li>Design your CSS architecture so you&#x2019;re not &#x201C;fighting&#x201D; your selectors.</li>
</ul>
<p>A well-structured CSS codebase makes debugging easier, reduces conflicts, and keeps your UI consistent.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Vector Databases - Explained for Developers]]></title><description><![CDATA[<p>As AI systems become more powerful, they also need smarter ways to store and search information. Traditional databases&#x2013;build for rows, columns, and exact matching&#x2013;struggle when dealing with meaning. That&apos;s where <strong>vector database</strong> come in.</p><h1 id="what-is-a-vector-database">What Is a Vector Database?</h1><p>A <strong>vector database</strong> - sometimes</p>]]></description><link>https://shiftasia.com/community/vector-databases-explained/</link><guid isPermaLink="false">692cff1118cce10001f0c81a</guid><category><![CDATA[AI]]></category><category><![CDATA[Database]]></category><dc:creator><![CDATA[MINATO Nguyen]]></dc:creator><pubDate>Fri, 05 Dec 2025 04:28:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/vt.png" medium="image"/><content:encoded><![CDATA[<img src="https://shiftasia.com/community/content/images/2025/12/vt.png" alt="Vector Databases - Explained for Developers"><p>As AI systems become more powerful, they also need smarter ways to store and search information. Traditional databases&#x2013;build for rows, columns, and exact matching&#x2013;struggle when dealing with meaning. That&apos;s where <strong>vector database</strong> come in.</p><h1 id="what-is-a-vector-database">What Is a Vector Database?</h1><p>A <strong>vector database</strong> - sometimes called a vector store or vector search engine - is a type of database designed to store and query data in <strong>vector form</strong>. A vector is a fixed-length array of numbers representing features of data such as text, images, audio, video, etc.</p><!--kg-card-begin: markdown--><p><code>&quot;This is a cat&quot; -&gt; [0.23, -0.14, 0.88, ...]</code></p>
<!--kg-card-end: markdown--><p>This is different from traditional databases (e.g., SQL), which are optimized for structured data (tables, rows, columns). With complex or unstructured data, vector databases enable meaning-based (semantic) search using high-dimensional space representations.</p><h1 id="why-developers-need-vector-database">Why Developers Need Vector Database?</h1><p>For unstructured data, key-word-based search is not enough. If the keyword does not match exactly, traditional search engines fail. Vector databases solve problems that traditional SQL or NoSQL systems cannot:</p><ul><li>Semantic search: Find content that means the same thing, even if the wording is different.</li><li>Scalability: Efficiently search millions or billions of embeddings.</li><li>Speed: Use specialized indexing for fast nearest-neighbor search.</li><li>Multimodal support: Word equally well with text, image, audio and more.</li></ul><p>Which AI applications growing fast&#x2013;chatbots, automation tools, RAG systems, ... Vector database have become part of the new infrastructure stack.</p><h1 id="how-vector-database-work">How Vector Database Work</h1><ol><li>Embedding Generation: Data (a sentence, an image...) is fed into a model that transforms it into a vector. These vectors capture relationships and meaning.</li><li>Vector Indexing: Instead of scanning everything, vector databases use algorithms like HNWS or IVF to quickly locate the nearest vectors in high-dimensional space.</li><li>Similarity Search:<br>When a user sends a query:<br>	- The query is embedded into a vector. 	<br>	- The database finds the closest stored vectors.<br>	- Results are returned based on similarity, not keywords.<br>This is the core of semantic search.</li><li>Metadata Filtering (Optional): Developers can mix vector search wich traditional fields to refind results (e.g., date, category, tags).</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://shiftasia.com/community/content/images/2025/12/vector-flow.png" class="kg-image" alt="Vector Databases - Explained for Developers" loading="lazy" width="2000" height="979" srcset="https://shiftasia.com/community/content/images/size/w600/2025/12/vector-flow.png 600w, https://shiftasia.com/community/content/images/size/w1000/2025/12/vector-flow.png 1000w, https://shiftasia.com/community/content/images/size/w1600/2025/12/vector-flow.png 1600w, https://shiftasia.com/community/content/images/2025/12/vector-flow.png 2100w" sizes="(min-width: 720px) 720px"><figcaption>Simple vector database workflow</figcaption></figure><h1 id="using-a-vector-database-in-python-chromadb">Using a Vector Database in Python (ChromaDB)</h1><ol><li>Install dependencies:</li></ol><!--kg-card-begin: markdown--><p><code>pip install chromadb sentence-transformers</code></p>
<!--kg-card-end: markdown--><p>2. &#xA0; Create embeddings for your documents</p><!--kg-card-begin: markdown--><pre><code>from sentence_transformers import SentenceTransformer

model = SentenceTransformer(&quot;all-MiniLM-L6-v2&quot;)

documents = [
    &quot;Python is a popular programming language.&quot;,
    &quot;Cats are small domesticated animals.&quot;,
    &quot;Machine learning enables computers to learn.&quot;
]

# Convert to vectors
embeddings = model.encode(documents).tolist()</code></pre>
<!--kg-card-end: markdown--><p>3. &#xA0; Create a Chroma vector database and insert documents</p><!--kg-card-begin: markdown--><pre><code>import chromadb

client = chromadb.Client()

collection = client.create_collection(name=&quot;my_docs&quot;)

collection.add(
    documents=documents,
    embeddings=embeddings,
    ids=[f&quot;doc_{i}&quot; for i in range(len(documents))]
)</code></pre>
<!--kg-card-end: markdown--><p>4. &#xA0; &#xA0;Perform a semantic search query</p><!--kg-card-begin: markdown--><pre><code>query = &quot;What helps computers learn?&quot;

query_vector = model.encode([query]).tolist()

result = collection.query(
    query_embeddings=query_vector,
    n_results=2
)

print(results)
</code></pre>
<!--kg-card-end: markdown--><p>Expected Output:</p><!--kg-card-begin: markdown--><pre><code>{
    &apos;documents&apos;: [
        [&apos;Machine learning enables computers to learn&apos;],
        [&apos;Python is a popular programming language&apos;]
     ]
}
</code></pre>
<!--kg-card-end: markdown--><h1 id="real-world-use-cases">Real-World Use Cases</h1><ul><li>RAG (Retrieval-Augmented Generation).</li><li>Semantic search for documents and knowledge bases.</li><li>Product and content recommendations.</li><li>Image and audio similarity search.</li><li>Fraud and anomaly detection.</li></ul><h1 id="how-to-get-started">How to Get Started</h1><ol><li>Choose and embedding model (text, image, or multimodal).</li><li>Pick a vector database (Milvus, Pinecone, Chroma, etc).</li><li>Setup an ingestion pipeline: data -&gt; embeddings -&gt; vector storage.</li><li>Build a query flow: user query -&gt; embedding -&gt; similarity search -&gt; results.</li></ol><h1 id="final-thoughts">Final Thoughts</h1><p>Vector databases bridge the gap between raw data and meaning. They allow developers to create apps that understand context, similarity, and semantics&#x2013;capabilities that traditional database simply weren&apos;t designed for. In the age of AI, vector databases are becoming a fundamental tool in every developer&apos;s stack.</p>]]></content:encoded></item><item><title><![CDATA[Why Revit API Is a Singleton]]></title><description><![CDATA[<h2 id="understanding-the-singleton-design-in-revit-api">Understanding the Singleton Design in Revit API</h2><p>The Revit API is designed around a singleton-like architecture, and this is intentional. Let&#x2019;s explore why this design choice matters for developers.</p><ol><li><strong>Revit Is a Single Application Instance</strong><br>Revit runs as one application process. All models, views, and UI interactions happen</li></ol>]]></description><link>https://shiftasia.com/community/why-revit-api-is-a-singleton/</link><guid isPermaLink="false">69257e5218cce10001f0c335</guid><category><![CDATA[BIM]]></category><dc:creator><![CDATA[JIM Trinh]]></dc:creator><pubDate>Fri, 05 Dec 2025 04:25:00 GMT</pubDate><media:content url="https://shiftasia.com/community/content/images/2025/12/Designer--2-.png" medium="image"/><content:encoded><![CDATA[<h2 id="understanding-the-singleton-design-in-revit-api">Understanding the Singleton Design in Revit API</h2><img src="https://shiftasia.com/community/content/images/2025/12/Designer--2-.png" alt="Why Revit API Is a Singleton"><p>The Revit API is designed around a singleton-like architecture, and this is intentional. Let&#x2019;s explore why this design choice matters for developers.</p><ol><li><strong>Revit Is a Single Application Instance</strong><br>Revit runs as one application process. All models, views, and UI interactions happen within this single environment. Allowing multiple API instances would create conflicts and instability.</li><li><strong>Consistency and Data Integrity</strong><br>The Revit model is a complex database of elements. If multiple API instances could modify the model independently, it would risk data corruption. A singleton ensures one point of control for all operations.</li><li><strong>Controlled Access to Core Objects</strong><br>Objects like UIApplication, UIDocument, and Document are tied to the active Revit session. The API provides these through a single entry point (ExternalCommandData.Application), so developers always work with the correct context.</li><li><strong>Transaction Management</strong><br>Revit requires all changes to occur inside a Transaction. A singleton approach ensures transactions are managed consistently across the entire application, preventing overlapping or conflicting changes.</li><li><strong>Performance and Stability</strong><br>Multiple API instances would increase memory usage and complexity. A singleton keeps the API lightweight and stable, which is critical for a BIM platform handling large models.</li></ol><h3 id="in-short">In Short</h3><p>The Revit API acts like a singleton because Revit itself is a single-instance application, and this design guarantees data integrity, stability, and predictable behavior for developers.</p><h3 id="sample-code-proving-singleton-behavior">Sample Code: Proving Singleton Behavior</h3><pre><code class="language-C#">using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.Attributes;

[Transaction(TransactionMode.Manual)]
public class SingletonDemo : IExternalCommand
{
    public Result Execute(
        ExternalCommandData commandData,
        ref string message,
        ElementSet elements)
    {
        // Get UIApplication from ExternalCommandData
        UIApplication uiApp1 = commandData.Application;
        UIApplication uiApp2 = commandData.Application;

        // Compare both instances
        bool isSameInstance = object.ReferenceEquals(uiApp1, uiApp2);

        // Show result
        TaskDialog.Show(&quot;Revit API Singleton&quot;,
            $&quot;Are both UIApplication instances the same? {isSameInstance}&quot;);

        return Result.Succeeded;
    }
}</code></pre><h3 id="explanation">Explanation</h3><ul><li><code>commandData.Application</code> always returns the same UIApplication object for the current Revit session.</li><li>Even if you call it multiple times, the reference is identical <code>ReferenceEquals</code> returns <code>true</code>).</li><li>This proves the API provides a single point of access to the Revit application context&#x2014;similar to a singleton pattern.</li></ul><h2 id="conclusion">Conclusion</h2><p>The Revit API&#x2019;s singleton-like design is not accidental&#x2014;it&#x2019;s a deliberate choice to ensure stability, consistency, and security within a single-instance application. By providing one unified access point to core objects like UIApplication, UIDocument, and Document, the API prevents conflicts, maintains data integrity, and simplifies transaction management.<br>For developers, understanding this architecture is crucial. It means you can confidently build plugins and automation tools knowing that the API enforces a predictable and controlled environment. In short, the singleton pattern in Revit API is what makes customization safe and scalable for complex BIM workflows.</p>]]></content:encoded></item></channel></rss>