<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Boraxpr</title><description>Boraxpr Personal Blog, where I share my thoughts on programming, technology, and more.</description><link>https://boraxpr.github.io</link><item><title>Simplify Your Code with Guard Clauses and Logical Expressions.</title><link>https://boraxpr.github.io/posts/logic</link><guid isPermaLink="true">https://boraxpr.github.io/posts/logic</guid><pubDate>Wed, 20 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When you start learning to code, after your initial &quot;Hello, World!&quot; program, one of the first constructs you encounter is the if-else statement. It&apos;s a fundamental part of programming, but it can quickly lead to complex and convoluted code if not used wisely. In this article, we&apos;ll explore how to simplify your code by avoiding nested if statements and employing guard clauses and logical expressions.&lt;/p&gt;
&lt;h2&gt;The Nested If Challenge 😫&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;is_sunny = True
temperature = 25
is_weekend = False
is_holiday = True
has_garden = False

if is_sunny:
    if temperature &amp;gt; 20:
        if not has_garden:
            print(&quot;It&apos;s a great day for a picnic!&quot;)
        else:
            print(&quot;We can&apos;t have a picnic today, no garden available.&quot;)
    elif is_weekend and is_holiday:
        if not has_garden:
            print(&quot;It&apos;s a great day for a picnic!&quot;)
        else:
            print(&quot;We can&apos;t have a picnic today, no garden available.&quot;)
    else:
        print(&quot;We can&apos;t have a picnic today, temperature is too low.&quot;)
else:
    print(&quot;We can&apos;t have a picnic today, it&apos;s not sunny.&quot;)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Admit it, this code is not the easiest to read or maintain.&lt;/p&gt;
&lt;h2&gt;Guard Clauses: A Cleaner Alternative ✨&lt;/h2&gt;
&lt;p&gt;To keep your code straightforward and easy to understand, consider using guard clauses. Guard clauses allow you to handle exceptional cases first and return early from a function or method. This eliminates the need for deeply nested if-else blocks.&lt;/p&gt;
&lt;p&gt;Don&apos;t do these 💀&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (A != null) {
  if (B != null){
    //do1
  }
  else {
    return;
  }
}
else {
  return;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do these 😇&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (A == null) {
  return;
}
if (B = null) {
  return;
}
//do1
//do2
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Combining Conditions for Clarity 🔍&lt;/h2&gt;
&lt;p&gt;After eliminating excessive if-else nesting, consider combining conditions when dealing with multiple variables. This simplifies your code and reduces the need for labyrinthian logic.&lt;/p&gt;
&lt;p&gt;Don&apos;t do these 💀&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (A){
  //before check B
  if (B){
    //before check C
    if (C){
      //...
      if (D){
        //...
        if (E){
          //do1
        }
        //...
      }
      //...
    }
    //after check C
  }
  //after check B
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do these 😇&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (A and B and C and D and E){
    //do1
  }
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, for even more clarity, consider breaking conditions into seperate lines 😇😇😇&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (A){}
if (B){}
if (C){}
//...
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Simplifying Conditional Logic in Action 🚀&lt;/h2&gt;
&lt;p&gt;Now, let&apos;s apply these concepts to simplify the code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;is_sunny = True
temperature = 25
is_weekend = False
is_holiday = True
has_garden = False

if is_sunny and (temperature &amp;gt; 20 or (is_weekend and is_holiday)) and not has_garden:
    print(&quot;It&apos;s a great day for a picnic!&quot;)
else:
    print(&quot;We can&apos;t have a picnic today.&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By implementing guard clauses and simplifying conditional logic, you can make your code more readable, maintainable, and less error-prone. Whether you&apos;re a beginner or an experienced developer, these practices will help you produce cleaner and more efficient code.&lt;/p&gt;
&lt;p&gt;In summary, code simplicity is not just a preference; it&apos;s a best practice that leads to better software development. Embrace these techniques to make your codebase more approachable and enjoyable to work with.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Low code, The code is low until it is not.</title><link>https://boraxpr.github.io/posts/lowcode</link><guid isPermaLink="true">https://boraxpr.github.io/posts/lowcode</guid><pubDate>Fri, 22 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Low code is not as straightforward as it might appear. While it may initially seem like an easy, error-free solution for developers, the reality is quite different. Low code can indeed simplify your life, but only until your project&apos;s requirements dictate otherwise.&lt;/p&gt;
&lt;h2&gt;The Front-End Challenge&lt;/h2&gt;
&lt;p&gt;Low code platforms allow you to create user interfaces without requiring in-depth knowledge of HTML, CSS, or JavaScript. You can simply drag and drop elements like inputs, forms, buttons, and tables. There are even helper actions to pull data onto the screen and generate tables automatically. These pre-made UI elements promise speed and efficiency, making you feel like you can deliver quickly—assuming your project aligns with the pre-made UI components.&lt;/p&gt;
&lt;p&gt;In practice, such alignment with pre-made UIs is rare. Customers and designers often demand customizations that involve CSS adjustments. This is where low code becomes a daunting challenge. Pre-made UIs come with their own pre-existing CSS code, making it challenging to modify them. Finding the right CSS class to edit can be a struggle, and you might end up reinventing the wheel by resorting to vanilla CSS, without the convenience of libraries.&lt;/p&gt;
&lt;p&gt;In high-code environments, you have access to reusable React components, which can be more efficient than the low code alternative.&lt;/p&gt;
&lt;h2&gt;Being Locked in the Environment&lt;/h2&gt;
&lt;p&gt;While low code platforms may offer some libraries, they may fall short when you need a specific one. Integrating external libraries can be far from straightforward, with limited documentation and poor integration with the low code platform itself.&lt;/p&gt;
&lt;h2&gt;The Risk of Reinventing the Wheel&lt;/h2&gt;
&lt;p&gt;When importing well-tested and proven libraries is impossible, and your project requirements exceed the capabilities of your low code platform, you&apos;re left with no choice but to write your own code. This can be time-consuming and prone to bugs, whereas high-code environments offer the convenience of utilizing existing libraries to save time and effort.&lt;/p&gt;
&lt;p&gt;In summary, low code can simplify development, but it&apos;s essential to recognize its limitations. It&apos;s &quot;low&quot; until your project&apos;s unique demands push you into the complexities of custom CSS, limited library options, and potentially reinventing solutions.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;In essence, low code serves as a higher-level abstraction of high code, but the closed nature of low code platforms frequently necessitates subpar high-code workarounds, ultimately compromising software quality.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Demystifying: CSS The Transition from Vanilla CSS to TailwindCSS</title><link>https://boraxpr.github.io/posts/css</link><guid isPermaLink="true">https://boraxpr.github.io/posts/css</guid><pubDate>Fri, 27 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I first got into programming during college, I was all about C, Python, and Java. Web development, with CSS and JavaScript, seemed like a whole different world. Fast forward to my new gig at a company, and I&apos;ve spent months wading through the CSS waters. I want to share what I&apos;ve learned and why I&apos;m warming up to Cascading Style Sheets.&lt;/p&gt;
&lt;h2&gt;The HTML Riddle&lt;/h2&gt;
&lt;p&gt;Fire up your favorite web browser and open a developer console. For me, I&apos;m on Firefox so it&apos;s ctrl+shift+I.
&lt;img src=&quot;./image-1.png&quot; alt=&quot;Alt text&quot; /&gt;
Now, go to any website and click on the inspector tool. You&apos;ll see the HTML code that makes up the page. It&apos;s a tree-like structure of tags and content.
Like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;My Page&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;My Page&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;My first paragraph&amp;lt;/p&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the HTML code for a simple page. It has a title, a heading, and a paragraph. The tags are the building blocks of the page. They tell the browser what to display and how to display it. But there&apos;s a catch.&lt;/p&gt;
&lt;h2&gt;The HTML Challenge: It&apos;s Not Pretty&lt;/h2&gt;
&lt;p&gt;HTML is great for structuring content, but it&apos;s not so good at making it look good. You can&apos;t change the font size, color, or spacing. You can&apos;t even make a simple box. That&apos;s where CSS comes in.&lt;/p&gt;
&lt;h2&gt;The CSS Riddle&lt;/h2&gt;
&lt;p&gt;CSS was a head-scratcher at the beginning. It didn&apos;t behave like the familiar programming languages I knew. But as I got into it, I started to decode its mysteries.&lt;/p&gt;
&lt;p&gt;With CSS, you can dress up your web content. You make classes with your names and decide how they should look. Like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.myFirstClass {
  /* CSS properties */
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These classes can be imported into your HTML code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;myFirstClass&quot;&amp;gt;
  &amp;lt;!-- HTML content --&amp;gt;
&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything inside this HTML tag adopts the specified CSS properties. But there&apos;s more.&lt;/p&gt;
&lt;h2&gt;CSS Tricks: Targeting Things&lt;/h2&gt;
&lt;p&gt;One of CSS&apos;s magic tricks is the ability to target nested elements. Let&apos;s say you want to style mySecondClass, but only when it&apos;s inside a myFirstClass tag. You can do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.myFirstClass .mySecondClass {
  /* CSS properties */
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is called a descendant selector. It&apos;s a powerful tool that allows you to target specific elements in your HTML code.&lt;/p&gt;
&lt;h2&gt;Borrowing from the Basics&lt;/h2&gt;
&lt;p&gt;CSS is not just about custom classes. You can also inherit and extend styles from predefined HTML elements. For instance, &apos;a&apos; tags come with default values:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a {
  color: blue;
  text-decoration: underline;
  cursor: auto;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that when you use an anchor tag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;a href=&quot;www.yourlink.com&quot;&amp;gt;Link Text&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It always has an underline, a default cursor, and the default link color. It&apos;s like the CSS magic got passed down through the generations.&lt;/p&gt;
&lt;h2&gt;The CSS Challenge: It Gets Messy&lt;/h2&gt;
&lt;p&gt;As I got better at CSS, I bumped into a common problem - keeping the old styles while bringing in new ones. It&apos;s like a slippery slope. What begins as a simple task can quickly turn into a maze of CSS classes, leading to a mess that&apos;s hard to clean up.&lt;/p&gt;
&lt;h2&gt;Enter TailwindCSS&lt;/h2&gt;
&lt;p&gt;In my search for a solution, I found TailwindCSS, and it&apos;s made my life easier.&lt;/p&gt;
&lt;p&gt;TailwindCSS simplifies styling. It gives you a set of ready-made classes, so you don&apos;t have to write loads of custom CSS. You style HTML elements by picking and using these classes directly.&lt;/p&gt;
&lt;p&gt;It&apos;s super convenient. You select and apply TailwindCSS classes for your HTML elements without piling up tons of custom CSS. But there are trade-offs. Your HTML might get longer, and you have to learn TailwindCSS&apos;s class names.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;CSS might seem confusing at first, but once you get the hang of it, it&apos;s a powerful tool. Whether you go for old-school custom CSS or embrace the simplicity of TailwindCSS, the key is to create good-looking and functional web stuff. Happy coding! 🚀&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Art of Tailwind CSS</title><link>https://boraxpr.github.io/posts/tailwinds</link><guid isPermaLink="true">https://boraxpr.github.io/posts/tailwinds</guid><pubDate>Wed, 17 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;TailwindCSS is a utility-first CSS framework. It is a set of CSS classes that you can use to style your HTML elements. It is not a UI library like Bootstrap or Material UI. It is a CSS framework that you can use to build your own UI library. Assuming you have a basic understanding of HTML and CSS, you can use TailwindCSS to build your own UI library.&lt;/p&gt;
&lt;h1&gt;Animate&lt;/h1&gt;
&lt;p&gt;One of the hardest thing to do is Animation
In tailwind.config.js, you can add your own animation.
Keyframes are the animation that you want to do. Animation is the name of the animation that you want to do.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module.exports = {
  content: [
    &apos;./app/**/*.{js,ts,jsx,tsx,mdx}&apos;,
    &apos;./components/**/*.{js,ts,jsx,tsx,mdx}&apos;
  ],
  theme: {
    extend: {
      keyframes: {
        shake: {
          &apos;0%, 100%&apos;: { transform: &apos;translate3d(0, 0, 0)&apos; },
          &apos;10%, 30%, 50%, 70%, 90%&apos;: { transform: &apos;translate3d(-10px, 0, 0)&apos; },
          &apos;20%, 40%, 60%, 80%&apos;: { transform: &apos;translate3d(10px, 0, 0)&apos; }
        }
      },
      animation: {
        shake: &apos;shake 1s ease-in-out&apos;
      }
    }
  },
  plugins: []
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that, you can use the animation in your HTML element.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div className=&quot;animate-shake&quot;&amp;gt;Shake me!&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Arbitrary Values&lt;/h1&gt;
&lt;p&gt;You can use arbitrary values in TailwindCSS. For example, if you want to set the width of an element to 100px, you can do it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div className=&quot;w-[100px]&quot;&amp;gt;My Element&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also use arbitrary values in the &lt;code&gt;@apply&lt;/code&gt; directive. For example, if you want to set the width of an element to 100px, you can do it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@layer base {
  .my-element {
    @apply w-[100px];
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can use the &lt;code&gt;my-element&lt;/code&gt; class like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div className=&quot;my-element&quot;&amp;gt;My Element&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can&apos;t use it for animations though.&lt;/p&gt;
&lt;h1&gt;Don&apos;t make components for default HTML elements&lt;/h1&gt;
&lt;p&gt;You do not need to make components for default HTML elements to reuse TailwindCSS classes. Things like button, input, p tag, etc. You can override them by using the &lt;code&gt;@apply&lt;/code&gt; directive at @layer base.&lt;/p&gt;
&lt;p&gt;@layer base on globals.css is the base layer. It is the default style of the HTML elements. You can override the default style by using the @layer base directive. For example, if you want to override the default style of the &lt;code&gt;h1&lt;/code&gt; element, you can do it like this on your globals.css file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@layer base {
  h1 {
    @apply text-4xl font-bold text-gray-900;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can use the &lt;code&gt;h1&lt;/code&gt; element like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;My Title&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even for the &lt;code&gt;button&lt;/code&gt; element, you can override the default style like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@layer base {
  button {
    @apply px-4 py-2 text-white bg-blue-500 rounded-md;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can use the &lt;code&gt;button&lt;/code&gt; element like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;button&amp;gt;My Button&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then poof!, all your buttons will have the same style.&lt;/p&gt;
&lt;h1&gt;Reuse : Do make components for custom elements&lt;/h1&gt;
&lt;p&gt;You can make components for custom elements. For example, if you want to make a card, you can do it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function handleClick() {
  const { data, error } = await someAPICalls
  redirect(&apos;/some-page&apos;)
}
;&amp;lt;Card
  customTailwindClasses=&quot;bg-red-50 border-red-200 rounded-lg&quot;
  customFunction={() =&amp;gt; handleClick}
&amp;gt;
  &amp;lt;span&amp;gt;My Card&amp;lt;/span&amp;gt;
  &amp;lt;span&amp;gt;Card detail&amp;lt;/span&amp;gt;
&amp;lt;/Card&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can make a component for it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Card.tsx
import React from &apos;react&apos;

export default function Card({
  children,
  customTailwindClasses,
  customFunction
}: {
  children: React.ReactNode
  customTailwindClasses?: string
  customFunction?: () =&amp;gt; void
}) {
  return (
    &amp;lt;div className={`${customTailwindClasses}`} onClick={customFunction}&amp;gt;
      {children}
    &amp;lt;/div&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Understanding Docker Multi-Stage Builds</title><link>https://boraxpr.github.io/posts/docker_multistage</link><guid isPermaLink="true">https://boraxpr.github.io/posts/docker_multistage</guid><pubDate>Sun, 25 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Docker has revolutionized the way we develop, package, and deploy applications. It provides a way to run applications isolated in containers, which are lightweight and include everything needed to run the application. One of the key features of Docker is the ability to build images using a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.&lt;/p&gt;
&lt;h2&gt;What are Multi-Stage Builds?&lt;/h2&gt;
&lt;p&gt;In Docker, a multi-stage build is a process where you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.&lt;/p&gt;
&lt;p&gt;The primary reason behind using multi-stage builds is to keep the final images small in size. The smaller the image, the faster it can be transferred and the less disk space it takes up.&lt;/p&gt;
&lt;h2&gt;Why Use Multi-Stage Builds?&lt;/h2&gt;
&lt;h3&gt;1.Image Size&lt;/h3&gt;
&lt;p&gt;When building Docker images, size matters. A smaller Docker image will lead to faster deployment times, which is critical in a CI/CD environment. It also reduces the attack surface area and thus improves security.&lt;/p&gt;
&lt;h3&gt;2.Build-Time Dependencies&lt;/h3&gt;
&lt;p&gt;There might be some dependencies required during the build time, but not needed in the runtime. With multi-stage builds, you can install these dependencies in the first stage where the building happens and not include them in the final stage.&lt;/p&gt;
&lt;h3&gt;3. Separation of Build and Run Stages&lt;/h3&gt;
&lt;p&gt;With multi-stage builds, you can use one base image for building the application and a different image for running the application. This separation can lead to more efficient images. For example, you might need a full-fledged Rust environment to build a Rust application, but you might only need a minimal Fedora image to run it.
An Example of Multi-Stage Build&lt;/p&gt;
&lt;p&gt;Here’s an example of a Dockerfile for a Rust application using multi-stage builds:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Use an official Rust runtime as a parent image

FROM rust:1.76 as builder

# Set the working directory in the container to /usr/src/rust_axum_service

WORKDIR /usr/src/rust_service

# Copy the current directory contents into the container at /usr/src/rust_axum_service

COPY . .

# Build the application

RUN cargo build

# Start a new stage. This is for the runtime environment

FROM fedora:41 as runtime

# Install openssl and ca-certificates and other dependencies that will be needed

RUN dnf -y update &amp;amp;&amp;amp; dnf -y install openssl-devel ca-certificates &amp;amp;&amp;amp; dnf clean all

# Set the working directory in the container to /usr/local/bin

WORKDIR /usr/local/bin

# Copy the binary from builder to this new stage

COPY --from=builder /usr/src/rust_service/target/debug/app /usr/local/bin

# Run the binary executable

CMD [&quot;./app&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Docker&apos;s multi-stage builds feature is a powerful tool for creating efficient Docker images. By separating build and runtime environments and selectively copying artifacts between stages, you can create smaller, more secure Docker images. This leads to faster deployment times and less disk space usage, making it beneficial in a production environment. As always, it&apos;s important to understand your application&apos;s specific needs and adjust your Dockerfile accordingly.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Beyond CRUD: Architecting Backends with Modern Languages</title><link>https://boraxpr.github.io/posts/modern_backend</link><guid isPermaLink="true">https://boraxpr.github.io/posts/modern_backend</guid><pubDate>Mon, 26 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, I&apos;ve stumbled across the newer languages and frameworks that are prevalent and expected by the dev community to be the future of backend.
I tried Rust &lt;a href=&quot;https://github.com/tokio-rs/axum&quot;&gt;tokio-rs/axum&lt;/a&gt; the framework way and also Go minimalistic net/http way. And incorporated best practices in the architecture.&lt;/p&gt;
&lt;h2&gt;Routing Layer&lt;/h2&gt;
&lt;p&gt;The routing layer is responsible for defining the URL paths for incoming requests. It acts as the entry point for requests, directing them to the appropriate handler based on the specified path.&lt;/p&gt;
&lt;h2&gt;Middleware Layer&lt;/h2&gt;
&lt;p&gt;Middleware functions as a pre-handler, allowing you to run code before passing the request to the handler. This is commonly used for tasks such as validation, authentication, logging, and request processing. Middleware helps to modularize and reuse code across different parts of your application.&lt;/p&gt;
&lt;h2&gt;Handler/Controller Layer&lt;/h2&gt;
&lt;p&gt;The handler/controller layer serves as the bridge between the frontend and backend. It receives incoming data from the frontend, processes it, and sends outgoing data back to the frontend. This layer plays a crucial role in handling user requests and orchestrating the flow of data within the application.&lt;/p&gt;
&lt;h2&gt;Service Layer&lt;/h2&gt;
&lt;p&gt;The service layer is where complex business logic resides. It abstracts away the logic from the handler/controller layer, keeping it clean and focused. This layer is particularly useful for handling complex operations that would otherwise clutter the handler/controller code.&lt;/p&gt;
&lt;h2&gt;Data Access/Repository Layer&lt;/h2&gt;
&lt;p&gt;The data access layer is responsible for interacting with the database and performing data operations. It handles low-level tasks such as SQL queries, data manipulation, and database transactions. Separating this layer from the rest of the application logic helps maintain a clear separation of concerns and improves overall code maintainability.&lt;/p&gt;
&lt;p&gt;By understanding and implementing these architectural principles, developers can create robust, scalable, and maintainable backend systems. While the specific technologies and languages may vary, the core concepts remain consistent, making these principles applicable across a range of backend development scenarios.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Cookie-Token based Authentication (Client-To-Server)</title><link>https://boraxpr.github.io/posts/auth</link><guid isPermaLink="true">https://boraxpr.github.io/posts/auth</guid><pubDate>Sat, 02 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Authentication is one of the hardest thing to do. Even when almost every application that you need to implement nowadays (Client-To-Server), needs an authentication system.
Today, I&apos;m going to debunk the myth of the authentication in both front and backend.&lt;/p&gt;
&lt;h2&gt;The Problem : Front-end&lt;/h2&gt;
&lt;p&gt;Front-End should not be able to access the cookie. Confusing isn&apos;t it ? Exposing a cookie or any token on front-end is just pure WRONG with CAPS because it allows anyone with JavaScript steal your identity. How are we going to implement protected routes ? you might ask.&lt;/p&gt;
&lt;h2&gt;The Key : Set-Cookie &amp;amp; HttpOnly&lt;/h2&gt;
&lt;p&gt;Invented back in 2002 by Microsoft Internet Explorer developers, HttpOnly is a flag that you could set inside &quot;Set-Cookie&quot; HTTP response header.
How is this important ? Because Set-Cookie header that you send from server-side is automatically captured by the client-side, and every subsequence requests to the server by the same origin will be attached with the cookie without any intervention from the client-side.
This way, You prevent all access from client-side and the only way hacker could do you wrong is to mess with the server. Cross-site scripting (XSS) would be the past problem. On top of that, set SameSite Attribute = Strict or Lax helps mitigate Cross-Site Request Forgery(CSRF) attacks.&lt;/p&gt;
&lt;h2&gt;How-To&lt;/h2&gt;
&lt;h3&gt;The Front-End&lt;/h3&gt;
&lt;p&gt;Whether you are using Framework like Nuxt, Vue, Next or library like React to do a multi-page app, you are going to have a router.
That router, you can do a middleware. Every route changes you need to call the server-side to check session. If True, Allow access. If False, Redirect to Login Page. And that&apos;s it for the Front-End.&lt;/p&gt;
&lt;h3&gt;The Back-End&lt;/h3&gt;
&lt;p&gt;Back-End is the main actor here. You need /login, /session and some knowledge about JWT.
JavaScript Object Notation Web Token. Ok, just ignore that. Basically, JWT is a base64 encoded text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;The JWT&lt;/h3&gt;
&lt;p&gt;Anyone can decode JWT, sees its content. But Only the one with its pro·gen·i·tor &quot;SECRET&quot; is able to edit, verify and create more JWT cute childlings. Hence, JWTs can provide data integrity, authenticity but lacks confidentiality.&lt;/p&gt;
&lt;p&gt;Now, After you know about the JWT secret and their ability to create more childs.&lt;/p&gt;
&lt;h3&gt;The Back-End &amp;amp; JWT interaction&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;/login&lt;/strong&gt;: After successfully verify username and password, response with cookie (Don&apos;t forget to use Set-Cookie to make the browser automatically handles the cookie safely) and user info.
&amp;lt;br&amp;gt;
&lt;strong&gt;/session&lt;/strong&gt; : Will check the cookie from the client (Automatically sent on every subsequences)&lt;/p&gt;
&lt;p&gt;Here is more things you need to know. Cookie Expiration controls how long the cookie will be stored and sent by the browser. Once it has expired, the browser will not include it in requests to the server. JWT Expiration controls the validation on the server-side. The secret and the expiry of JWT will be cross checked on parsing and JWT childs that passed their expiry are invalid.&lt;/p&gt;
&lt;h3&gt;The limitations&lt;/h3&gt;
&lt;p&gt;This method of cookie-token has one of its downside being when you need multiple domain to call the server apis. If that&apos;s the case then you would need &quot;Token based Authentication&quot; which is basically everything Cookie-Token Based Authentication is minus &quot;Set-Cookie&quot;. Now you need to send the JWT token via header &quot;Authorization: Bearer [Your token]&quot; (This format is a socially accepted. But it&apos;s not enforced by the client because you will need to do it all manually for using Token-based Authentication.) and on the client-side you would need to manually unpack it and store it somewhere (LocalStorage, SessionStorage, Cookie, Application Memory, Web Worker). And then you would need to include the said token on every requests to the apis. And use backend auth middleware implementation to intercept and verify all requests. However, there will be nuances of security issues in this method that requires more effort such as utilizing encryption and hashing algorithms. That is also take a toll on the performance on each token retrieval.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, the keywords are JWT secrets (Secret can be used to verify, create more JWT child), Set-Cookie (Let your browser automate cookie management far out of JavaScript reach), Use the server and finally do not trust the client.&amp;lt;br&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie&lt;/a&gt;
&lt;a href=&quot;https://owasp.org/www-community/HttpOnly&quot;&gt;https://owasp.org/www-community/HttpOnly&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Coding is not Going Anywhere: Disagreeing with Jensen Huang</title><link>https://boraxpr.github.io/posts/nope</link><guid isPermaLink="true">https://boraxpr.github.io/posts/nope</guid><pubDate>Mon, 04 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There has been a significant push from online courses, influencers, and governments promoting the idea that everyone should learn to code. The push is fueled by the booming popularity of online courses promising to help anyone change their careers. Anyone can be a software engineer, software developer, software tester, et cetera.&lt;/p&gt;
&lt;h3&gt;The Turning Point&lt;/h3&gt;
&lt;p&gt;Recently, Jensen Huang, CEO of Nvidia, made headlines with his statement: &quot;Don&apos;t learn to code.&quot; At the World Government Summit in Dubai, he furthered this narrative by suggesting that AI will replace coders, stating, &quot;Everyone is now a programmer.&quot;&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe width=&quot;100%&quot; height=&quot;300px&quot; src=&quot;https://www.youtube.com/embed/6Lcy2N3YcIs?si=baOEsfpi2l5a5Deq&amp;amp;start=42&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;p&gt;Firstly, I want to clarify that I&apos;m not opposed to AI. It&apos;s helpful, save my time and potentially will remedy the labor shortages due to the aging society in next 20 years but it won&apos;t kill programmers.&lt;/p&gt;
&lt;h3&gt;LLMs : A Limitation&lt;/h3&gt;
&lt;p&gt;The current approach to AI, particularly with Large Language Models (LLMs), does not embody true &quot;Artificial Intelligence.&quot; LLMs lack consciousness, reasoning, logic, and understanding.
LLMs excel in processing vast amounts of data and mapping patterns to generate answers.
However, problem-solving is not a simple copy-and-paste operation. It requires a deep understanding of the problem itself.
Of course, If you insert Leetcode style problems into your LLMs, they will be able to solve because these types of problems are used over and over again.
Like University Admissions Exams. There are only few original problems and they only change the wordings. And the solutions are all over the internet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./image.png&quot; alt=&quot;alt text&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Here is the 2025 update: After ChatGPT was debunked, attempts were made to patch hallucinations. However, if users provide incorrect information, LLMs will still hallucinate&lt;/em&gt;
&lt;img src=&quot;./image-3.png&quot; alt=&quot;alt text&quot; /&gt;
🤦&lt;/p&gt;
&lt;p&gt;&amp;lt;br&amp;gt;Here is an image that I try to make up &quot;King Mantisoraya&quot; asking LLM &quot;who is King Mantisoraya&quot;.
The LLM replies suggested that Mantisoraya is a character from the anime and manga &quot;Yu-Gi-Oh!&quot;.
However, after I try to search on Google, I find nothing closely related to the name of the character in Yu-Gi-Oh anime.&lt;/p&gt;
&lt;p&gt;LLMs look promising and feel promising because the premise is that all their outcomes are human responses. They have been designed to do so. They might replace your tinder girlfriends. They are best at knowing what you want as a response but worst for the truth-seeking and problem-solving.&lt;/p&gt;
&lt;p&gt;LLM lacks true understanding. That’s why they will never be able to guarantee their response correctness based on their internal understanding. Basing on statistics, LLM is bound to always be sound correctful that’s why they will always be hallucinating. At its core, hallucination is LLM core. That alone would put them in a place that is unable to replace human.&lt;/p&gt;
&lt;h3&gt;A Future Perspective&lt;/h3&gt;
&lt;p&gt;In the future, there might be new ways to approach AI. It may be programmer replacing AI. But sorry LLMs, it&apos;s not today.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Balancing Complexity and Simplicity in Frontend Development</title><link>https://boraxpr.github.io/posts/beyondcode</link><guid isPermaLink="true">https://boraxpr.github.io/posts/beyondcode</guid><pubDate>Sun, 10 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the world of frontend development, simplicity is often overlooked in favor of the latest and trendiest technologies. As developers, we&apos;re bombarded with new libraries, frameworks, and tools that promise to revolutionize our workflow and deliver unparalleled results. However, this pursuit of innovation can sometimes lead us down a path of over-engineering, where we create solutions that are far more complex than the problems they&apos;re meant to solve.&lt;/p&gt;
&lt;h2&gt;The Allure of New Technologies&lt;/h2&gt;
&lt;p&gt;It&apos;s easy to fall into the trap of over-engineering, especially when faced with the pressure to keep up with the latest trends. Influencers and experts constantly tout new libraries and frameworks as the &quot;must-have&quot; tools for any project, leading to a culture of constant churn and unnecessary complexity.&lt;/p&gt;
&lt;p&gt;For example, a simple project that could be completed with a few essential libraries suddenly requires the integration of four or five additional frameworks, all in the name of staying up-to-date with the &quot;META&quot; stack of tooling. This trend is reminiscent of gaming channels on YouTube, where content creators focus on the latest updates and strategies.&lt;/p&gt;
&lt;h2&gt;The Problem with Over-Engineering&lt;/h2&gt;
&lt;p&gt;Over-engineering not only adds unnecessary complexity to our projects but also creates new problems in the process. By adopting multiple frameworks and libraries without a clear understanding of their purpose or how they fit into the overall solution, we risk creating bloated and unmaintainable codebases.&lt;/p&gt;
&lt;p&gt;Moreover, this approach can be particularly harmful to beginners, who are just starting to learn the basics of programming. Instead of focusing on fundamental concepts and problem-solving skills, they&apos;re bombarded with information about the &quot;latest and greatest&quot; tools, which may not always be the best fit for their needs.&lt;/p&gt;
&lt;h2&gt;Embracing Simplicity and Practicality&lt;/h2&gt;
&lt;p&gt;It&apos;s essential to remember that there is no silver bullet in software development. Stacks and technologies come and go, but the fundamentals remain the same. Rather than blindly following trends, we should focus on understanding the problem at hand and choosing tools that solve that problem effectively and efficiently.&lt;/p&gt;
&lt;p&gt;By embracing simplicity and practicality in our development practices, we can avoid the pitfalls of over-engineering and create more maintainable and scalable applications. Let&apos;s prioritize understanding the problem, choosing the right tools for the job, and building solutions that stand the test of time.&lt;/p&gt;
&lt;h2&gt;The Allure of Libraries for Simple Tasks&lt;/h2&gt;
&lt;p&gt;JavaScript developers are often tempted to use libraries for even the simplest of tasks. Whether it&apos;s adding a date picker or creating a modal dialog, there&apos;s a library out there that promises to make the job easier. While libraries can indeed save time and effort, they can also introduce unnecessary complexity into a project.&lt;/p&gt;
&lt;p&gt;One of the main reasons developers reach for libraries is convenience. It&apos;s easier to npm install a package than to write custom code, especially for tasks that seem mundane or repetitive. However, this convenience comes at a cost. Every library added to a project increases its dependency footprint and potential for conflicts or vulnerabilities.&lt;/p&gt;
&lt;p&gt;Moreover, the use of libraries can sometimes lead to a lack of understanding of the underlying concepts. When developers rely too heavily on libraries, they may not fully grasp the fundamentals of the task at hand. This can be particularly problematic when troubleshooting issues or trying to optimize performance.&lt;/p&gt;
&lt;h2&gt;Striking a Balance&lt;/h2&gt;
&lt;p&gt;While libraries can be incredibly useful, especially for complex tasks or when working under time constraints, it&apos;s essential to strike a balance between convenience and necessity. Before reaching for a library, developers should ask themselves if the task truly requires it, or if it can be accomplished with simpler, more lightweight solutions.&lt;/p&gt;
&lt;p&gt;By being more selective about the libraries we use and taking the time to understand the problem we&apos;re solving, we can avoid over-engineering and create more efficient and maintainable codebases. Let&apos;s prioritize simplicity and practicality in our development practices, and choose tools that truly enhance our workflow without adding unnecessary complexity.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Scientific Coding</title><link>https://boraxpr.github.io/posts/why</link><guid isPermaLink="true">https://boraxpr.github.io/posts/why</guid><pubDate>Tue, 26 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;The how is what you needed most for getting anything done. But in order to connect the dots, you must collectively consider the why.
Years of experience often be one of the most gauge when it comes to perceivable effectiveness of devs.
However, It&apos;s so easy to have 1 years of experience 10 times and call it 10 years experience.&lt;/p&gt;
&lt;h3&gt;Scientific Coding&lt;/h3&gt;
&lt;p&gt;It&apos;s important to avoid using faith in programming. It always has a cost when all you understand is &quot;it just works&quot;. The price is you never grow. Moreover, the memorization over understanding increases the probability of preaching to everyone that it needs to be done that way.&lt;/p&gt;
&lt;p&gt;For database, 3-4 years ago it&apos;s MongoDB, &quot;we all must use NoSQL because it scales&quot;.
For frontend, it&apos;s React, &quot;we all must use React [insert arguments here]&quot;.&lt;/p&gt;
&lt;p&gt;In reality, it&apos;s all about the why. It&apos;s harder to understand why. You must know why before you analytically know what tools should be used to solve the problem.&lt;/p&gt;
&lt;h3&gt;Why?&lt;/h3&gt;
&lt;p&gt;Frameworks, Libraries and programming languages , depends on how deep you want to go, have been built upon layers and layers of underlying implementations. The problem is that, while it makes app building easier, it also makes it harder to understand what&apos;s going on behind the code. Let&apos;s say you started out learning React as your first tool you ever known. While React is a great way to quickly build apps and see instant results. It&apos;s important that you also understand core programming concepts. You would never understand why React (in a scientific sense) when you never try vanilla JavaScript, jQuery, other frameworks (Vue, Svelte, Angular, etc.).&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Instead of chasing the hype, we should focus on understanding the problems, the tools and the solution. Learning is good but make sure you learn the why.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>HOT TAKE: I do not use ORMs - Why it should not be used on production, ever</title><link>https://boraxpr.github.io/posts/idontuseorm</link><guid isPermaLink="true">https://boraxpr.github.io/posts/idontuseorm</guid><pubDate>Thu, 04 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Object-Relational Mapping (ORM) is an anti-pattern that should be avoided at all costs.&lt;/p&gt;
&lt;h2&gt;Reasons to avoid ORMs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Violation of Separation of Concerns: ORMs void the separation of concerns between the database and the application.&lt;/li&gt;
&lt;li&gt;N+1 Query Problem: Most ORMs lead to N+1 query problems that you will notice only after it runs on production servers. N+1 query problems refer to N extra number of queries executed instead of a single optimized query.&lt;/li&gt;
&lt;li&gt;Complexity and Learning Curve: ORMs require developers to work with unfamiliar APIs to achieve optimal SQL code generation.&lt;/li&gt;
&lt;li&gt;Abstraction Overhead: Newer ORMs are marketed as &quot;SQL-Like&quot;. If it&apos;s SQL-like, Why not just use SQL? Instead of having a giant pile of magic abstraction in data layers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reasons to use SQL instead of ORMs&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Universality and Simplicity: SQL is the most common programming language used for database management systems. Every university course teaches SQL. Recruiting developers ? It&apos;s more likely that they know SQL than your specific ORM library.&lt;/li&gt;
&lt;li&gt;Control and Performance: SQL is considered straightforward and essential, especially for complex projects where direct control over database queries is necessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Debunk 1 : Use ORM now !!, What would you do when we need to change the database in the future ?&lt;/h2&gt;
&lt;p&gt;Companies often avoid changing their databases due to compliance concerns, as any modifications can impact compliance requirements significantly. In large organizations, there&apos;s a strong emphasis on data tracking and logging to ensure that every action taken on the database is traceable and logged for audit purposes. The cost of changing production databases is high and is not advisable as it might leads to data loss and data corruption. The benefits just do not outweigh the cost.&lt;/p&gt;
&lt;h2&gt;Debunk 2 : Use ORM now !!, Why use the complex-hard-labourly SQL when you have the Easy-to-Use ORM ?&lt;/h2&gt;
&lt;p&gt;When it comes to ORM, while suitable for simpler projects or short-term applications, there&apos;s a risk of missing out on developing SQL and DBMS skills, which are crucial in the long run for more complex projects. In general, SQL is considered straightforward and essential, once you learn how to use it. You know it forever. Unlike some ORMs, which maintainers may abandon within the next 3 months if they do not generate enough traffic or if the maintainers are simply bored and want to create a new one. For toy projects or short-lived applications, ORM can be a suitable choice if you do not want to develop and grow as a developer.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;For simple projects on production, I would still be against using ORMs. Initially, every project starts as a simple CRUD application. Over time, projects inevitably become more complex.
For simple projects, using SQL is easier and straightforward as well. The latest ORMs promise no n+1 query problems, SQL-like APIs. But why does it matter? When you can simply learn and use SQL. It&apos;s highly valued because it has been researched, battle-tested, and proven to work since 1974 (that&apos;s over 50 years ago!). While many languages from that period have faded away, SQL is still widely used and relevant. Let that sink in.
SQL is declarative and highly readable, almost like your everyday english. It&apos;s even more readable than Python. It&apos;s easy to learn and use. That&apos;s why it has been used widely for over 50 years and will be used in the future.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Object Oriented Programming as intended by the original creator, Alan Kay</title><link>https://boraxpr.github.io/posts/composition</link><guid isPermaLink="true">https://boraxpr.github.io/posts/composition</guid><pubDate>Sat, 20 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In object oriented programming, It&apos;s widely taught, misunderstood, misused that inheritance is &quot;the basic building block&quot; of OOP by the books.&lt;/p&gt;
&lt;p&gt;It&apos;s undeniable that most courses, whether it is an online course or university course, placed a lot of emphasis on inheritance making every new programmer think that Object Oriented Programming is about inheritance.&lt;/p&gt;
&lt;p&gt;They always give examples like there is Animal then we need to create a Dog, a Cat, etc. That&apos;s literally the first example, the first step of learning OOP everywhere.&lt;/p&gt;
&lt;p&gt;Visiting any tutorials or textbooks, 99.99% of the time, you will find that they talk about inheritance and they would give you an example similar to this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Car {
  private String color;
  private String brand;
  private String model;

  public void drive() {
    System.out.println(&quot;Driving&quot;);
  }

  public void fillFuel() {
    System.out.println(&quot;Filling fuel&quot;);
  }
}

class SportsCar extends Car {
  private String engineType;
  public void startEngine() {
    System.out.println(&quot;Starting engine&quot;);
  }
}

class LuxuryCar extends Car {
  private String engineType;
  public void startEngine() {
    System.out.println(&quot;Starting engine&quot;);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The Problem with Inheritance&lt;/h2&gt;
&lt;p&gt;The problem with inheritance is, it locks down the code forever. Says, one day there is a new type of car that do not play well with the traditional Car. Like an EV car that requires a whole new way to fill fuel. EV cars need to be charged instead of using Gasoline. That&apos;s when inheritance fails. Because it voids the Open/Closed Principle.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a class should be open for extension but closed for modification.
The deeper into the class hierarchy,
the more difficult it is to add new features.
the more difficult it is to change existing features.
the more chances it is to introduce new bugs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Voiding the Open/Closed Principle, it&apos;s the best way to create a spaghetti code destroying multiple of normally working classes at once. Now, the base class will be the single point of failure, god object.&lt;/p&gt;
&lt;h2&gt;The Composition Approach&lt;/h2&gt;
&lt;p&gt;Inheritance is &quot;is a&quot; and composition is &quot;has a&quot;. Instead of fixate on how something is, we create room for composition. Now we design classes based on what they has.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
class Car {
  private String color;
  private String brand;
  private String model;
}

interface Driveable{
  default void drive() {
    System.out.println(&quot;Driving&quot;);
  }
}

interface Fuelable{
  void fillFuel();
  default void startEngine() {
    System.out.println(&quot;Starting fuel engine&quot;);
  }
}

interface Chargeable{
  void charge();
  default void startEngine() {
    System.out.println(&quot;Starting electric engine&quot;);
  }
}

class sportsCar extends Car implements Driveable, Fuelable {
}

class EVCar extends Car implements Driveable, Chargeable {
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Utilizing strategy pattern, we can create classes based on what they has. This design has the advantage of being modular and reusable.
However, as you can see, it still uses inheritance.
For maximize the flexibility, never tie any cars to the Car class.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Car {
  private String color;
  private String brand;
  private String model;
}

interface Driveable{
  default void drive(Car car) {
    System.out.println(&quot;Driving&quot;);
  }
}

interface Fuelable{
  void fillFuel(Car car);
  default void startEngine(Car car) {
    System.out.println(&quot;Starting fuel engine&quot;);
  }
}

interface Chargeable{
  void charge(Car car);
  default void startEngine(Car car) {
    System.out.println(&quot;Starting electric engine&quot;);
  }
}

class sportsCar implements Driveable, Fuelable {
}

class EVCar implements Driveable, Chargeable {
}

class HybridCar implements Driveable, Fuelable, Chargeable {
  public void startEngine(Car car) {
    System.out.println(&quot;Starting hybrid engine&quot;);
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another thing that we can do is, we can use generic type to allow interfaces to be more flexible.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
class Car {
  private String color;
  private String brand;
  private String model;
}

class Bike {
  private String color;
  private String brand;
  private String model;
}

interface Driveable&amp;lt;T&amp;gt; {
  default void drive(T self) {
    System.out.println(&quot;Driving&quot;);
  }
}

interface Fuelable&amp;lt;T&amp;gt; {
  void fillFuel(T self);
  default void startEngine(T self) {
    System.out.println(&quot;Starting fuel engine&quot;);
  }
}

interface Chargeable&amp;lt;T&amp;gt; {
  void charge(T self);
  default void startEngine(T self) {
    System.out.println(&quot;Starting electric engine&quot;);
  }
}

class sportsCar implements Driveable&amp;lt;Car&amp;gt;, Fuelable&amp;lt;Car&amp;gt; {
}

class roadBike implements Driveable&amp;lt;Bike&amp;gt;, Fuelable&amp;lt;Bike&amp;gt; {
}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of fixing these interfaces to allow just Car, we can use generic type. This opens up new possibilities of implementing by other types. For example, Bike that can also implement Driveable (Not a Car).&lt;/p&gt;
&lt;h2&gt;Benefits of Composition&lt;/h2&gt;
&lt;p&gt;Now, any new class can be flexibly created based on what they have without any lockdown that you are going to inherit from a specific class (Never need to modify deep in the class hierarchy ever again).&lt;/p&gt;
&lt;p&gt;Composition makes Loose Coupling possible while adhere to Open/Closed Principle.&lt;/p&gt;
&lt;h2&gt;Inheritance has its place&lt;/h2&gt;
&lt;p&gt;Inheritance can be used to avoid attribute duplication.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Machinery {
  private String weight;
  private boolean isWorking; 
  private boolean isAutomata;
}

class Car extends Machinery {
  private String color;
  private String brand;
  private String model;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inheritance should not be used for behavior in object-oriented programming. Doing so leads to tight coupling, a rigid class hierarchy, and spaghetti-unmaintainable code. Many developers mistakenly use inheritance for behavior, considering it as true object-oriented programming. However, in true object-oriented programming, inheritance is used to model relationships between objects. Objects interact with each other through messages and method calls, emphasizing meaningful relationships and interactions over organizing code around data structures and operations.&lt;/p&gt;
&lt;p&gt;Let&apos;s write the maintainable, reusable, testable code by using OOP as intended by the original creator.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Stop Forcing React to Re-render: Here’s a Better Way</title><link>https://boraxpr.github.io/posts/react-antipattern-1</link><guid isPermaLink="true">https://boraxpr.github.io/posts/react-antipattern-1</guid><pubDate>Thu, 20 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;React, the most popular JavaScript framework for building user interfaces, leverages state management to efficiently update and re-render components. In the early days of web development, developers relied on vanilla JavaScript or libraries like jQuery to perform partial page updates using AJAX. React simplifies this by automatically re-rendering components when the state changes.&lt;/p&gt;
&lt;h2&gt;Re-rendering with setState&lt;/h2&gt;
&lt;p&gt;React detects changes and triggers re-renders when the state is updated using the setState method (or the useState hook in functional components). Here’s a simple example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const [example, setExample] = useState({ Apple: 1, Banana: 8, Orange: 4 })

// Re-render is triggered on set state
setExample({ Apple: 7, Banana: 8, Orange: 4 })
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The Problem with Direct State Mutation&lt;/h2&gt;
&lt;p&gt;A common anti-pattern in React is directly mutating the state and then setting it back. This approach does not trigger a re-render because React uses shallow comparison to detect state changes. If the reference to the state object does not change, React assumes the state has not changed.
🚫&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Get the default value
let tmpExample = example
// Mutate the state
tmpExample[Apple] = 7
// Set it right back
setExample(tmpExample)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What happen is the screen will not be rerendered because the object id has not changed.&lt;/p&gt;
&lt;h2&gt;Force Re-rendering as an Anti-pattern&lt;/h2&gt;
&lt;p&gt;To force a re-render, some developers introduce a boolean state variable. This approach can work but is considered an anti-pattern because it complicates the code and can lead to unexpected behaviors.
🚫&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const [rerender, setRerender] = useState(false)

// Get the default value
let tmpExample = example
// Mutate the state
tmpExample[Apple] = 7
// Set it right back
setExample(tmpExample)

// Trigger the rerender
setRerender(!rerender)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this method triggers a re-render, it is not recommended. It adds unnecessary complexity and can be confusing to others maintaining the code.&lt;/p&gt;
&lt;h2&gt;The Proper Way: Shallow Copy&lt;/h2&gt;
&lt;p&gt;A better solution is to create a shallow copy of the state object and update the copy. This ensures that the reference changes, triggering React’s re-render mechanism.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const [example, setExample] = useState({ Apple: 1, Banana: 8, Orange: 4 })

// Re-render is triggered on set state
setExample({ Apple: 7, ...example })
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, the spread operator (...example) creates a shallow copy of the example object. The Apple property is updated, and the new object is passed to setExample, ensuring that React detects the change and re-renders the component.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using the spread operator to create a shallow copy of the state object is a best practice in React. It avoids the pitfalls of direct state mutation and force re-rendering, leading to more predictable and maintainable code. Remember, immutability is key to effectively managing state in React applications.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>RESTful and why it matters</title><link>https://boraxpr.github.io/posts/restful</link><guid isPermaLink="true">https://boraxpr.github.io/posts/restful</guid><pubDate>Thu, 20 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In modern web development, creating clear and manageable paths for your APIs and frontend routes is crucial. Take a look at these examples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/api/create-a-new-post-in-the-database
/myPage/Product/Product-List/Product-Details/Edit-Product&amp;amp;id=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These paths are undeniably more complex than they need to be. They are not only difficult to read but also harder to maintain.
Imagine the app growing in complexity, and you have to keep track of all these paths.
This is where RESTful design comes into play, promoting simplicity and modularity.&lt;/p&gt;
&lt;h2&gt;Why RESTful Design ?&lt;/h2&gt;
&lt;p&gt;RESTful design is an architectural style that uses HTTP requests to access and manipulate data. It is based on a set of principles that ensure your API is easy to understand, scalable, and maintainable. Here’s why it matters:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Modularity and Reusability:
RESTful APIs are built around resources and use standard HTTP methods (GET, POST, PUT, DELETE) to perform operations on these resources. This modular approach allows you to reuse and extend your API easily.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scalability:
Since RESTful APIs are stateless, each request from a client to a server must contain all the information the server needs to fulfill that request. This makes it easier to scale your application horizontally, as any server can handle any request independently.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consistency and Predictability:
Using a consistent structure for your endpoints makes your API predictable. Developers can easily understand how to interact with your API without extensive documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Better Performance:
RESTful APIs can take advantage of HTTP caching mechanisms, which can reduce the load on the server and improve response times for clients.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Examples of RESTful Paths&lt;/h2&gt;
&lt;h3&gt;Non-RESTful Path&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/api/create-a-new-post-in-the-database
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;RESTful Path&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;POST /api/posts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, /api/posts is the resource, and POST is the HTTP method used to create a new post.&lt;/p&gt;
&lt;h3&gt;Non-RESTful Path&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/myPage/Product/Product-List/Product-Details/Edit-Product&amp;amp;id=1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;RESTful Path&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;GET /api/products/1
PUT /api/products/1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, /api/products is the resource. GET is used to fetch product details, and PUT is used to edit product details for the product with ID 1.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Adopting RESTful principles in your API design ensures that your paths are simple, modular, and maintainable. It enhances the scalability, consistency, and performance of your application, making it easier for developers to understand and use your API. By following RESTful design, you can create an API that is robust, flexible, and future-proof.&lt;/p&gt;
&lt;p&gt;So, when designing your next API, remember to keep it RESTful and embrace the benefits of simplicity and modularity.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>When DRY Becomes Too Dry: Avoiding Over-Complexification</title><link>https://boraxpr.github.io/posts/dry</link><guid isPermaLink="true">https://boraxpr.github.io/posts/dry</guid><pubDate>Fri, 12 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;hr /&gt;
&lt;p&gt;The idea of DRY is to avoid repetition. If multiple places use the same code, why should we write it multiple times? Instead, we should write it once and reuse it. This is a good practice and helps in maintaining the codebase. But sometimes, developers take this too far and end up over-complicating the codebase. This is when DRY becomes too dry.&lt;/p&gt;
&lt;h2&gt;When DRY Becomes Too Dry&lt;/h2&gt;
&lt;h3&gt;1. Abstraction Overload&lt;/h3&gt;
&lt;p&gt;One of the common pitfalls of overusing DRY is abstraction overload. Developers tend to create unnecessary abstractions to avoid repetition. While abstractions are good, too many of them can make the code hard to understand and maintain. It&apos;s essential to strike a balance between DRY and readability.&lt;/p&gt;
&lt;h3&gt;2. Premature Optimization&lt;/h3&gt;
&lt;p&gt;Another issue with overusing DRY is premature optimization. Developers try to optimize the code too early, even when it&apos;s not needed. This can lead to complex code that is hard to debug and maintain. It&apos;s better to keep the code simple and optimize only when necessary.&lt;/p&gt;
&lt;h3&gt;3. Tight Coupling&lt;/h3&gt;
&lt;p&gt;Overusing DRY can also lead to tight coupling between different parts of the codebase. When code is too abstracted and reused in multiple places, changing one part can have unintended consequences in other parts. It&apos;s essential to keep the code modular and loosely coupled.&lt;/p&gt;
&lt;h3&gt;4. Maintenance Nightmare&lt;/h3&gt;
&lt;p&gt;When DRY becomes too dry, it can turn into a maintenance nightmare. Developers spend more time understanding the code than actually fixing bugs or adding features. It&apos;s crucial to keep the codebase simple and easy to understand. Sometimes, a little repetition is better than over-complicating things. It&apos;s better to have a clear codebase than a DRY one. Let&apos;s say there is a new requirement, and you need to change the code. If the code is too abstracted and over-complicated, it can be challenging to make the necessary changes. On the other hand, if the code is simple and straightforward, making changes becomes easier.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;DRY is a good principle, but it&apos;s essential to use it wisely. Don&apos;t over-complicate things in the name of DRY. Sometimes, a little repetition is better than creating a complex codebase. Keep the code simple, modular, and easy to understand. Strike a balance between DRY and readability. Remember, when DRY becomes too dry, it&apos;s time to reevaluate your approach.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Being Lazy is the First Step Toward Creating a Maintainable Solution</title><link>https://boraxpr.github.io/posts/belazy</link><guid isPermaLink="true">https://boraxpr.github.io/posts/belazy</guid><pubDate>Wed, 30 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many developers fall into the trap of over-engineering solutions early on, thinking that complexity or a comprehensive feature set equates to a robust system. But in reality, simplicity is king.&lt;/p&gt;
&lt;p&gt;When approaching a problem, the first step toward maintainability is being &quot;lazy&quot; This doesn&apos;t mean avoiding work—it&apos;s about being strategic with your effort. By minimizing unnecessary code, dependencies, and convoluted architecture, you can focus on what&apos;s important. Leverage default behaviors, use out-of-the-box solutions where possible, and avoid reinventing the wheel unless you have no other choice.&lt;/p&gt;
&lt;p&gt;More code always comes at a cost. More dependencies always come at a cost. This cost is often hidden, and only a few truly notice it at first. A bloated codebase makes every future feature slower to develop, and maintenance becomes a burden. It’s easy to get caught up in adding feature after feature, but with each addition, you risk entangling the system in complexity that will slow down progress in the long run.&lt;/p&gt;
&lt;p&gt;More custom, non-default settings mean more things to fix when dependencies upgrade or deprecate. Each customization adds layers of complexity, and when third-party libraries or tools evolve, maintaining these customizations can become a nightmare.&lt;/p&gt;
&lt;p&gt;The beauty of a maintainable solution is that it&apos;s straightforward, predictable, and easy for others to pick up. If your codebase requires endless explanations or a detailed manual just to onboard someone new, it’s probably too complicated.&lt;/p&gt;
&lt;p&gt;Remember: good code is not about showing off complexity; it&apos;s about clarity, efficiency, and ease of maintenance. Keep it lazy, keep it simple, and future you (and your colleagues) will thank you for it!&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Dev contents in 2024 make no sense</title><link>https://boraxpr.github.io/posts/media</link><guid isPermaLink="true">https://boraxpr.github.io/posts/media</guid><pubDate>Thu, 07 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;While I appreciate the content that has helped me grow in the past, I’ve noticed a worrying trend in 2024 that seems to undermine its value. I&apos;ve always been a big fan of getting new knowledge by watching YouTube, TikTok, and Facebook posts about software development. However, there’s an ongoing trend that I&apos;m not so happy to see: more and more software development content is using fear-mongering tactics to trick us into clicking, preying on our FOMO (Fear of Missing Out).&lt;/p&gt;
&lt;p&gt;Many YouTube channels aimed at beginner software developers seem more focused on the profits than on providing real value. I’m not saying this out of bias—these were once my go-to sources for learning. But as time has passed, I feel like the quality has hit rock bottom.&lt;/p&gt;
&lt;p&gt;A common pattern in video titles includes phrases like &quot;Don&apos;t use Try Catch&quot; or &quot;What you&apos;re doing is totally wrong.&quot; When you click to watch, the content often reiterates things you already know, followed by a dramatic claim that you&apos;re doing something wrong. Then, the video quickly pivots to promoting sponsored products, online courses, or services they&apos;re trying to sell.&lt;/p&gt;
&lt;p&gt;The knowledge gained from these videos has steadily decreased, to the point where I consider them mostly clickbait. Maybe these videos are aimed at beginners, and I’m past that stage now.&lt;/p&gt;
&lt;p&gt;What I think is happening is that some creators focus more on exploiting insecurities than providing valuable insight. They capture our attention, then steer us toward their products, courses, and services that promise to fix our &quot;flaws.&quot; This is marketing 101. The substance doesn&apos;t match the hype, leaving people feeling less confident and like they&apos;re falling short—even though the original concern may not have been that significant. These creators make you feel lesser, implying that you always need their opinions, just to get you to stick around and watch their promotional content, all while gaining a constant flow of revenue.&lt;/p&gt;
&lt;p&gt;It’s exhausting to go into a video expecting improvement, only to leave feeling manipulated or sold to. This type of content capitalizes on emotions, making people feel like they need to constantly consume to improve, which can be overwhelming and counterproductive. I hope creators start focusing on delivering real, practical value rather than sensationalizing issues to sell products. In the end, we should strive to build each other up, not profit from each other&apos;s insecurities.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>React&apos;s Evolution: From Higher-Order Components to the Flexibility of Hooks</title><link>https://boraxpr.github.io/posts/hochook</link><guid isPermaLink="true">https://boraxpr.github.io/posts/hochook</guid><pubDate>Sun, 17 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the early days of React, Higher-Order Components (HoCs) were the go-to pattern for reusing logic across components. They offered a way to &quot;wrap&quot; additional behavior into a component, striving to follow the DRY (Don&apos;t Repeat Yourself) principle. But as React evolved, so did its patterns—and now, with Hooks, HoCs have become largely outdated.&lt;/p&gt;
&lt;h2&gt;Example: HoC vs. Hook&lt;/h2&gt;
&lt;p&gt;Here’s a practical comparison to illustrate the difference.&lt;/p&gt;
&lt;h3&gt;HoC Approach&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;function withLogger(WrappedComponent) {
  return function LoggerComponent(props) {
    console.log(&quot;Rendered with props:&quot;, props);
    return &amp;lt;WrappedComponent {...props} /&amp;gt;;
  };
}

const EnhancedComponent = withLogger(MyComponent);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works but tightly couples the logging logic to the wrapper. Removing or modifying it means touching every instance of withLogger.&lt;/p&gt;
&lt;h3&gt;Hook Approach&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;function useLogger(props) {
  useEffect(() =&amp;gt; {
    console.log(&quot;Rendered with props:&quot;, props);
  }, [props]);
}

function MyComponent(props) {
  useLogger(props);
  return &amp;lt;div&amp;gt;{props.text}&amp;lt;/div&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With Hooks, the logging logic is decoupled. You can add or remove useLogger in specific components without affecting the others.&lt;/p&gt;
&lt;p&gt;Here’s a closer look at why HoCs feel rigid and cumbersome compared to the flexible and composable nature of Hooks.&lt;/p&gt;
&lt;h2&gt;The Problem with HoCs: &quot;Wrap Everything Forever&quot;&lt;/h2&gt;
&lt;p&gt;HoCs operate on a simple idea: take a component, wrap it in another component that provides extra functionality, and pass everything down through props. On paper, this sounds great! However, in practice, HoCs have significant downsides:&lt;/p&gt;
&lt;h4&gt;Rigid and Hard to Manage&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Carved in the stone&lt;/strong&gt; : Once you wrap a component with an HoC, it’s difficult to untangle that behavior or change it. It’s like OOP inheritance—you&apos;re locked into the parent-child relationship.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wrapper Hell&lt;/strong&gt; : If you have multiple HoCs wrapping the same component, debugging turns into a nightmare, as you deal with &quot;wrapper hell.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Overengineering in the Name of DRY&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;God Component Trap&lt;/strong&gt; : HoCs aim to avoid repeating code by centralizing logic, but this can lead to over-abstraction. Logic hidden inside a wrapper might make sense initially, but over time, it becomes harder to trace bugs or customize behavior.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prone to violate the Open/Close principle&lt;/strong&gt; : Adding or removing features requires modifying the HoC itself, potentially impacting every component it wraps. It&apos;s easy to end up with fragile, tightly coupled code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Enter Hooks: Reusable Lego Bricks&lt;/h2&gt;
&lt;p&gt;React Hooks (introduced in version 16.8) revolutionized how we share logic in React apps. Instead of wrapping components, Hooks offer utilities—small, focused, and composable pieces of logic you can use anywhere.&lt;/p&gt;
&lt;h3&gt;Why Hooks Work Better&lt;/h3&gt;
&lt;h4&gt;Flexibility Over Rigid Abstraction&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Hooks don’t force you into a specific structure. They’re just functions. You can freely add, remove, or combine Hooks without altering the component hierarchy.&lt;/li&gt;
&lt;li&gt;Need to reuse logic? Create a custom Hook that can be applied wherever needed—no wrappers required.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Readable and Debuggable&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;With Hooks, the logic is front and center, directly inside the component. This makes it easier to understand what’s happening, less context-switching, and simpler debugging.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;More Code, More Freedom&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Hooks may lead to some repetition (e.g., multiple components importing the same custom Hook), but this repetition gives you the freedom to customize logic on a case-by-case basis.&lt;/li&gt;
&lt;li&gt;It’s a pragmatic trade-off: a bit more typing in exchange for long-term maintainability.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;DRY vs. Maintainability&lt;/h2&gt;
&lt;p&gt;HoCs are a classic case of taking the &lt;strong&gt;DRY principle&lt;/strong&gt; too far. By striving for zero duplication, they end up coupling logic tightly to the wrapper, creating inflexible, monolithic abstractions.&lt;/p&gt;
&lt;p&gt;Hooks, on the other hand, embrace &lt;strong&gt;composition over inheritance&lt;/strong&gt;, focusing on building reusable utilities that are easy to add, modify, or remove. While this approach might feel less DRY at first glance, it ensures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ease of Debugging:&lt;/strong&gt; Logic is visible and accessible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintainability:&lt;/strong&gt; Small, focused pieces of logic are easier to refactor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; Components can evolve without being shackled to a wrapper.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Comparing HoCs and Hooks&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Higher-Order Components (HoCs)&lt;/th&gt;
&lt;th&gt;Hooks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Structure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Forces a wrapping hierarchy&lt;/td&gt;
&lt;td&gt;Flat, reusable functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debugging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard due to wrapper layers&lt;/td&gt;
&lt;td&gt;Easier with inline logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Coupled tightly to wrappers&lt;/td&gt;
&lt;td&gt;Decoupled and composable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Readability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Abstracted away in HoCs&lt;/td&gt;
&lt;td&gt;Directly visible in components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Harder due to global HoC impact&lt;/td&gt;
&lt;td&gt;Localized and focused utilities&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;The Verdict&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;HoCs are the result of wanting to be DRY but applying it too rigidly.&lt;/strong&gt; They over-centralize logic at the expense of flexibility and readability. &lt;strong&gt;Hooks, on the other hand, trade a bit of repetition for composability and long-term maintainability.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you’re starting a new React project or modernizing an old one, Hooks are the way forward. They’re not just a replacement for HoCs—they’re a more intuitive, flexible, and powerful paradigm for sharing logic in React.&lt;/p&gt;
&lt;p&gt;So, let’s leave &quot;wrap everything forever&quot; behind and embrace the future with &lt;strong&gt;reusable Lego bricks&lt;/strong&gt; that make our code easier to build and maintain.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>E2E Typesafety, tRPC, and T3 Stack: Overhyped Hype or Developer Trap?</title><link>https://boraxpr.github.io/posts/t3isscam</link><guid isPermaLink="true">https://boraxpr.github.io/posts/t3isscam</guid><pubDate>Sun, 24 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The buzz around &quot;&lt;strong&gt;Type-safe end-to-end&lt;/strong&gt;&quot; is impossible to ignore. With frameworks like the T3 Stack and tRPC, developers are promised seamless integration and foolproof data consistency. But here’s the harsh truth: the reality is far less glamorous. These tools may have their place, but they often fail to deliver on their promises—and sometimes, they make things worse.&lt;/p&gt;
&lt;p&gt;Let’s cut through the noise and expose why “E2E typesafety” is more of a mirage—and what you should be focusing on instead to build real, reliable systems.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;1. TypeScript: More Hype Than Help for E2E Typesafety&lt;/h3&gt;
&lt;p&gt;Let’s set the record straight: &lt;strong&gt;TypeScript doesn’t deliver “E2E typesafety”&lt;/strong&gt;—it’s a compile-time tool, and it has limits.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compile-Time Only&lt;/strong&gt;: TypeScript guarantees nothing &lt;strong&gt;at runtime&lt;/strong&gt;. Once your app is up and running, it’s on you to handle unvalidated data. Forget about trusting TypeScript alone—it’s not a magic bullet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JavaScript’s Chaos&lt;/strong&gt;: TypeScript can’t fix JavaScript’s mess. Dynamic data (like raw JSON) can break your app in ways TypeScript can’t prevent, leaving you with crashes when you least expect them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;False Confidence&lt;/strong&gt;: Just because TypeScript doesn&apos;t throw an error at compile time doesn’t mean you’re safe. In production, a minor type mismatch could lead to catastrophic issues you never saw coming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Wake Up&lt;/strong&gt;: TypeScript is great for catching bugs during development, but relying on it for runtime safety is reckless. Without runtime validation, your system is a ticking time bomb.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. The Database: Your True Data Guardian&lt;/h3&gt;
&lt;p&gt;Stop chasing the illusion of “E2E typesafety.” The real authority over data integrity is your &lt;strong&gt;database schema&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Schemas Do the Heavy Lifting&lt;/strong&gt;: Your database schema doesn’t ask for permission—it enforces rules at runtime. Constraints, data types, relationships: these are the things that ensure your data stays consistent. TypeScript types? Not even in the same league.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid the ORM Trap&lt;/strong&gt;: Tools like Prisma are tempting, but they often add layers of complexity you don’t need. A properly structured schema in PostgreSQL or MySQL is the real workhorse behind your app’s integrity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bottom Line&lt;/strong&gt;: TypeScript may help during development, but the &lt;strong&gt;real&lt;/strong&gt; guarantee of data integrity is your database schema. Without it, you’re gambling with your app’s reliability.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. Validators: The Non-Negotiable Safety Net&lt;/h3&gt;
&lt;p&gt;If you&apos;re skipping runtime validation, you&apos;re leaving your app &lt;strong&gt;wide open&lt;/strong&gt; to failure.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Don’t Skip Validation&lt;/strong&gt;: Libraries like Zod, Joi, or NestJS’s built-in validation tools aren’t optional—they’re &lt;strong&gt;required&lt;/strong&gt;. These libraries ensure the data entering your system is clean, safe, and trustworthy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guard Against the Wild West&lt;/strong&gt;: TypeScript can&apos;t protect you from untrusted user input or malicious data. You need a robust runtime validation layer to keep your app stable in the real world.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Stop pretending TypeScript will handle everything. Add runtime validation to catch errors where they matter most—&lt;strong&gt;at runtime&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4. tRPC and T3 Stack: Powerful but Not for the Long Haul&lt;/h3&gt;
&lt;p&gt;The T3 Stack and tRPC are sold as &lt;strong&gt;the answer&lt;/strong&gt; to your development woes, but here’s why you should be cautious:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tightly Coupled Systems&lt;/strong&gt;: tRPC thrives in a one-stack world like Next.js. But try integrating with other tools or scaling beyond that, and you’ll quickly realize you’ve painted yourself into a corner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vercel Lock-In&lt;/strong&gt;: The T3 Stack’s seamless integration with Vercel is fantastic—until it’s not. When you need to scale or move to other platforms like AWS, Azure or GCP, you’re left with an ecosystem that’s difficult to escape. Good luck with that.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API Flexibility? Forget It&lt;/strong&gt;: Need OpenAPI or GraphQL support? You won’t get it here. tRPC is built for one thing, and it’s not the kind of flexibility that large-scale systems demand.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Takeaway&lt;/strong&gt;: tRPC and the T3 Stack are great for small projects and rapid prototyping, but they’re a poor fit for scaling. They’re &lt;strong&gt;not&lt;/strong&gt; the long-term solution you’re looking for.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5. Serverless: Not the Silver Bullet&lt;/h3&gt;
&lt;p&gt;Serverless is all the rage in the T3 Stack, but it’s far from a universal solution. Here’s why it often &lt;strong&gt;fails&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cold Start Hell&lt;/strong&gt;: Serverless architectures come with &lt;strong&gt;cold start&lt;/strong&gt; latency issues that will slow you down, especially for high-traffic apps or real-time features. If performance matters to you, serverless is a liability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scaling Nightmares&lt;/strong&gt;: Moving away from serverless is a &lt;strong&gt;nightmare&lt;/strong&gt;. If you ever need to migrate to traditional servers or containers, expect a costly and time-consuming refactor. Not exactly a smooth transition.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Be Realistic&lt;/strong&gt;: Serverless is great for quick, small apps—but for any serious, high-performance project, it’s a &lt;strong&gt;poor choice&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;A Smarter Approach to Typesafety and Scalability&lt;/h3&gt;
&lt;p&gt;Stop chasing the “E2E typesafety” dream. Focus on building systems that are &lt;strong&gt;robust&lt;/strong&gt;, &lt;strong&gt;flexible&lt;/strong&gt;, and &lt;strong&gt;scalable&lt;/strong&gt;. Here’s the real formula for success:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Validate at Runtime&lt;/strong&gt;: TypeScript won’t save you. Use Zod, Joi, or NestJS validation tools to &lt;strong&gt;guarantee correctness at runtime&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trust Your Database Schema&lt;/strong&gt;: The database schema is the &lt;strong&gt;final authority&lt;/strong&gt; on data integrity. Design it well, and trust it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decouple Your Architectures&lt;/strong&gt;: Don’t lock yourself into a specific frontend or backend stack. Build flexible, decoupled systems that scale as needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Take Control of Deployment&lt;/strong&gt;: Use Docker, Kubernetes, or traditional servers to avoid vendor lock-in and maintain control over your infrastructure.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;Final Thoughts: Don’t Be Sucked In by the Hype&lt;/h3&gt;
&lt;p&gt;The hype around “E2E typesafety” is real, but it’s a trap. While tools like tRPC and the T3 Stack might offer some conveniences, they come with major limitations that could bite you later. Don’t get blinded by the shiny promises—focus on what actually works.&lt;/p&gt;
&lt;p&gt;By combining &lt;strong&gt;TypeScript for development-time safety&lt;/strong&gt;, &lt;strong&gt;runtime validation for production reliability&lt;/strong&gt;, and a &lt;strong&gt;robust database schema&lt;/strong&gt; for data integrity, you’ll build systems that are truly scalable and reliable—without falling into the trap of overhyped, one-size-fits-all solutions.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>AI Replacing Humans: The Reality of Agentic AI</title><link>https://boraxpr.github.io/posts/agenticai</link><guid isPermaLink="true">https://boraxpr.github.io/posts/agenticai</guid><pubDate>Sat, 22 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, I&apos;m going to talk about the recent topic that has been talked about a lot in the job world. Agentic AI. What is it? And why I don&apos;t think it&apos;s going to replace human anytime soon. Many have discussed this topic, but I’ll offer a real-world, practical take.&lt;/p&gt;
&lt;h2&gt;The Pricing&lt;/h2&gt;
&lt;p&gt;Current AI pricing models are token-based. For example, in OpenAI’s model, four characters equal one token. The more complex your prompt, the more it costs, with no guarantee that the AI will complete the task correctly. This means wasted money when the output isn’t useful.&lt;/p&gt;
&lt;h2&gt;The Productivity&lt;/h2&gt;
&lt;p&gt;AI agents aren’t as fast as you might think. You can’t just assign a task and expect it to be completed instantly. Processing is slow, and results are often inaccurate. Reports show that when agentic AI was asked to fix a minor text error, it took hours and still failed. In another case, a self-funded startup relied on agentic AI, but due to the founder’s lack of technical expertise, the project ended up with over 30 barely functional Python files.&lt;/p&gt;
&lt;h2&gt;The Real-World Agentic AI Everyone Talks About - Without the Hype&lt;/h2&gt;
&lt;p&gt;One of the most well-known agentic AI software engineers, Devin, has a buy-in cost of approximately 15,000 Thai Baht and comes with limited token usage. After the initial free tokens are used, additional tokens must be purchased. Despite being one of the most advanced agentic software engineers currently available, Devin is shockingly slow, turning a simple 3-5 minute task into an hour-long process. A simple configuration change can generate multiple unrelated files. While AI is bound to improve, at this rate, it won’t be replacing humans anytime soon.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An hour clip of Devin in action by ex-Netflix software engineer ThePrimeAgen &amp;lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/927W6zzvV-c?si=Rxe8wQUOjKbuGzwT&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;The bottom line&lt;/h2&gt;
&lt;p&gt;In today’s global economy, where remote work is widely available, hiring a human expert is often more cost-effective than using agentic AI—especially in regions with lower living costs. Humans offer more than just task completion; they provide insights, feedback, accountability, and adaptability. AI lacks these qualities, making it a less reliable alternative.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;While agentic AI is evolving, it remains costly, slow, and unreliable compared to human expertise. For now, hiring skilled professionals remains the smarter choice, especially for tasks demanding creativity, accountability, and critical thinking.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Once You See the Patterns, Every Framework Speaks the Same Language</title><link>https://boraxpr.github.io/posts/polyglot</link><guid isPermaLink="true">https://boraxpr.github.io/posts/polyglot</guid><pubDate>Sat, 10 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: I don’t chase frameworks — I trace patterns. I work best when I understand the full system. Once you see the design beneath the syntax, every framework starts to feel familiar. It’s not about how many years you’ve used X — it’s about how quickly you can see how X thinks.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Recently, someone asked me questions like:&lt;br /&gt;
&lt;em&gt;&quot;How many years have you used framework X, Y, Z?&quot;&lt;/em&gt;&lt;br /&gt;
&lt;em&gt;&quot;How long have you been working with language A, and are you comfortable with it?&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It got me thinking — not just about my past experience, but about what actually lets me cut through tools, languages, and stacks with understanding and intent.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;The Shift That Started It All&lt;/h3&gt;
&lt;p&gt;The story begins in 2018. Windows 10 — in its notorious version 1809 update — nuked my personal files. Gone. Coursework, notes, everything. The moment that happened, I made a decision: never again. I wasn’t going to trust an OS that careless with my work. I Googled alternatives. macOS? No thanks. And that’s how I ended up with Linux — by force, not fandom.&lt;/p&gt;
&lt;p&gt;Linux didn’t solve everything. But it made things fun. It pulled me into the real world of programming. I got into PyBites code challenges and caught fire — earning two certificates that lit a spark in me I didn’t even know was there. That passion made me curious — not just about Python, but &lt;em&gt;everything&lt;/em&gt; around it.&lt;/p&gt;
&lt;p&gt;Everything about the developer experience felt better on Linux — once you got past its quirks. Installing tools was dead simple. On Windows, you’re Googling installers, manually adding things to PATH, clicking through wizards. On Linux? It’s a single command: &lt;code&gt;sudo apt install [tool]&lt;/code&gt;. Most setups just work, and if they don’t, the logs usually tell you why.&lt;/p&gt;
&lt;p&gt;At first, I was stuck in the language war. I thought everything should be written in Python. But once I worked in production with Java, I immediately saw the difference: if we used Python in that environment, the system would’ve caught fire — literally — from runtime errors. That experience taught me the hard way: dynamic typing is harder to write safely than it looks. In fact, strict languages like Java or Go can be easier to build stable systems with, because they fail early — not in production.&lt;/p&gt;
&lt;p&gt;Once that realization clicked, I couldn’t stop. At my second workplace, I found myself in a low-code environment where I had to manually wrangle outdated CSS to meet design requirements. I remember thinking: &lt;em&gt;&quot;There has to be a better way than forcing visual changes through this brittle setup.&quot;&lt;/em&gt; That frustration pushed me toward frontend development — HTML, JS, React, Next, Vue, Nuxt, Svelte. Then I explored Rust. Then Go. Every new stack made me see the same thing more clearly:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;They’re all connected.&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;How I Learn: Systems First, Tools Second&lt;/h3&gt;
&lt;p&gt;I’ve learned that I can’t truly work on something unless I see the top-down view — the full map. That’s just how I operate. I need to see the universe — how all tools and languages fit together — before I choose the set I’ll use. And once I understand how a system designer thinks, I don’t fight the tool. I follow its grain. I use it the way it was meant to be used — not against its nature.&lt;/p&gt;
&lt;p&gt;Some non-tech folks think jumping between frameworks makes you shallow.&lt;br /&gt;
And sure — it can, if you&apos;re just chasing hype without asking &lt;em&gt;why&lt;/em&gt;.&lt;br /&gt;
But when you jump because you’re tracing patterns, because you want to understand the shape of things — that’s not shallow. That’s systems thinking.&lt;br /&gt;
Suddenly, everything connects. Everything gets sharper.&lt;/p&gt;
&lt;p&gt;Frontend frameworks all follow a common architecture. So do backend frameworks.&lt;br /&gt;
Each has its trade-offs, its strengths, its limitations.&lt;br /&gt;
Some frameworks give you freedom and power — but you pay for it with complexity.&lt;br /&gt;
Others are opinionated — and get out of your way, fast.&lt;br /&gt;
Community conventions shape the experience more than the syntax does.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Mapping Mental Models Across Stacks&lt;/h3&gt;
&lt;p&gt;So when I see &lt;strong&gt;NestJS&lt;/strong&gt;, I don’t just see TypeScript sugar — I see Angular’s influence, inversion of control, and dependency injection. In fact, it’s basically Spring Boot with a better developer experience.&lt;br /&gt;
When I see &lt;strong&gt;Java&lt;/strong&gt;, I don’t complain about verbosity — I understand why it exists, because I’ve seen what too much freedom in Python can cost.&lt;br /&gt;
When I see &lt;strong&gt;Go&lt;/strong&gt;, I don’t see safety like Rust — I see modern ergonomics. Pointers without the pain. Static typing without the ceremony. Simplicity by design, yet packed with just the features you need. It enforces OOP the right way — through composition with structs — unlike Java, where too much flexibility often leads to bloated, misused inheritance trees.&lt;br /&gt;
When I see &lt;strong&gt;Azure DevOps&lt;/strong&gt;, I see a managed, easier version of the bare-metal Jenkins and GitLab CI/CD pipelines I once built.&lt;br /&gt;
When I see &lt;strong&gt;Vue&lt;/strong&gt;, I see React’s component model — just rendered through templates instead of JSX.&lt;br /&gt;
When I see &lt;strong&gt;Tailwind&lt;/strong&gt;, I see modular, utility-first CSS done right — unlike the tangled, manual CSS hierarchies I once had to wrangle in a low-code platform.&lt;br /&gt;
When I see &lt;strong&gt;Spring Boot&lt;/strong&gt;, I see echoes of .NET Core — same enterprise scaffolding, different dialect.&lt;/p&gt;
&lt;p&gt;Not because I’ve used all of them for years — but because I’ve studied their shape, their model, and their intention.&lt;/p&gt;
&lt;p&gt;Because once you’ve seen enough patterns, you realize most frameworks are the same game — just with different dice.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Design Is the Real Fluency&lt;/h3&gt;
&lt;p&gt;This isn’t about mastering syntax. It’s about recognizing that every serious framework is just a system of assumptions, opinions, and constraints.&lt;br /&gt;
And once you see the scaffolding, you can operate in any ecosystem.&lt;/p&gt;
&lt;p&gt;You stop asking &lt;em&gt;“How many years have you used this?”&lt;/em&gt; and start asking &lt;em&gt;“How does this thing think?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s what lets developers jump stacks with confidence — the ability to see the structure behind the syntax.&lt;/p&gt;
&lt;p&gt;I don’t measure fluency by surface familiarity.&lt;br /&gt;
I measure it by how fast I can find the edges of a system, where the pain points lie, and — most importantly — knowing &lt;strong&gt;what to look for in the documentation&lt;/strong&gt; to move forward.&lt;/p&gt;
&lt;p&gt;Because at a certain point — if you’ve really paid attention — every framework speaks the same language.&lt;br /&gt;
And it’s not JavaScript or Python.&lt;br /&gt;
It’s &lt;strong&gt;design&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I don’t aim to be a god of one specific technology — because stacks come and go.&lt;br /&gt;
What stays is the ability to see how systems work at their core. That’s the real future-proofing.&lt;br /&gt;
&lt;strong&gt;Once you understand the fundamentals, the stack becomes the icing — not the cake.&lt;/strong&gt;&lt;br /&gt;
The real focus should be on design, intention, and what you’re building.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>The Cost of a &quot;User-Driven&quot; System with No Filters</title><link>https://boraxpr.github.io/posts/userdriven</link><guid isPermaLink="true">https://boraxpr.github.io/posts/userdriven</guid><pubDate>Sat, 17 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Database&lt;/strong&gt; without Primary Key, Foreign Key, Constraint&lt;br /&gt;
→ &lt;strong&gt;Spreadsheet + GUID cosplay&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Project Owner&lt;/strong&gt; without System Ownership, Product Vision/Direction, Accountability&lt;br /&gt;
→ &lt;strong&gt;A feature wishlist printer who doesn’t know how the app works&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Business Engineer&lt;/strong&gt; without Decision Confidence, Technical Understanding, Flow Awareness, Prioritization&lt;br /&gt;
→ &lt;strong&gt;A fear-driven feedback generator&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dev&lt;/strong&gt;&lt;br /&gt;
→ &lt;strong&gt;Left customizing code and architecture based on reactive emotional fear&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&quot;Here, we do whatever the user wants.&quot;&lt;/strong&gt;&lt;br /&gt;
That was the moment I realized: this isn’t product development — this is chaos management.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;Here’s what that really means:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No product ownership&lt;/li&gt;
&lt;li&gt;No logic gate between wishful thinking and production&lt;/li&gt;
&lt;li&gt;No pushback, no filtering, no prioritization&lt;/li&gt;
&lt;li&gt;Just BA/BE acting as &lt;strong&gt;human forward bots&lt;/strong&gt;, dumping raw input on devs&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;What happens next:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The system bends to every fear, every whim, every “what if”&lt;/li&gt;
&lt;li&gt;Business logic turns into duct tape&lt;/li&gt;
&lt;li&gt;Flow becomes an emotional rollercoaster&lt;/li&gt;
&lt;li&gt;And engineers?&lt;br /&gt;
→ We become the &lt;strong&gt;sanity firewall&lt;/strong&gt; — rewriting backend code to accommodate feelings, not facts&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Reality check:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User-driven ≠ user-ruled.&lt;/strong&gt;&lt;br /&gt;
Building software is not the same as saying yes to everything.&lt;/li&gt;
&lt;li&gt;If no one protects the system, it will rot — no matter how many devs you hire.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;Posted from the last stage of a glamorous AI project built on a low-code database with no primary key.&lt;/em&gt;&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>What Is Database Pooling — and Why So Many People Get It Wrong</title><link>https://boraxpr.github.io/posts/dbpool</link><guid isPermaLink="true">https://boraxpr.github.io/posts/dbpool</guid><pubDate>Fri, 06 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This issue is rampant in &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;Go&lt;/strong&gt;, and &lt;strong&gt;Python&lt;/strong&gt; — basically anywhere you&apos;re &lt;em&gt;not&lt;/em&gt; using a meta-framework like Java Spring Boot or Python Django.&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;contractor-heavy environments with no real code reviews&lt;/strong&gt;, things like this slip through. And they &lt;strong&gt;quietly burn&lt;/strong&gt; your system with way more resource usage than necessary.&lt;/p&gt;
&lt;p&gt;Take this common anti-pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const sql = require(&apos;mssql&apos;);

var pool = await sql.connect(config);
var query = &quot;SELECT * FROM TABLE&quot;;
var result = await pool.request().query(query);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ve seen this copy-pasted into dozens of methods. One &lt;code&gt;connect()&lt;/code&gt; call per API. What’s wrong with it?&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;❌ Why This Is a Problem&lt;/h3&gt;
&lt;p&gt;Every time you call an endpoint, the app reconnects to the database:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Network call → Authenticate → Allocate new connection → Run query → Return result&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now imagine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Every API call&lt;/strong&gt; does this&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dozens or hundreds of users&lt;/strong&gt; hit the system&lt;/li&gt;
&lt;li&gt;You’re running in a &lt;strong&gt;limited connection pool&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your database gets hammered not by queries, but by &lt;strong&gt;connection spam&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When the pool overflows, the DB has to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Figure out which connections are idle&lt;/li&gt;
&lt;li&gt;Kill those&lt;/li&gt;
&lt;li&gt;Start new ones&lt;/li&gt;
&lt;li&gt;Authenticate again&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Maybe&lt;/em&gt; finally run your query&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is silent tech debt. And it scales like a time bomb.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;✅ How It’s Done Right&lt;/h3&gt;
&lt;p&gt;Frameworks like &lt;strong&gt;Spring Boot&lt;/strong&gt; have HikariCP under the hood — a high-performance connection pool you don’t even think about. You just inject &lt;code&gt;DataSource&lt;/code&gt; and go.&lt;/p&gt;
&lt;p&gt;In Node.js and other minimal stacks? &lt;strong&gt;You have to manage it yourself.&lt;/strong&gt;&lt;br /&gt;
At minimum:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db.js
const sql = require(&apos;mssql&apos;);
const poolPromise = sql.connect(config);
module.exports = poolPromise;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in your services:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// userService.js
const pool = await require(&apos;./db&apos;);
const result = await pool.request().query(&quot;SELECT * FROM Users&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One connection pool. Reused. As it should be.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;🧨 TL;DR&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Don’t &lt;code&gt;sql.connect()&lt;/code&gt; on every API call.&lt;br /&gt;
Connect once on app startup.&lt;br /&gt;
Reuse that pool. Always.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Otherwise, you&apos;re not building a backend — you&apos;re building a denial-of-service engine.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>[Off-topic] Why I Think Hot Countries Are Generally Less Developed Than Colder Countries</title><link>https://boraxpr.github.io/posts/heat</link><guid isPermaLink="true">https://boraxpr.github.io/posts/heat</guid><pubDate>Sun, 08 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;People often talk about colonialism, politics, or geography when explaining why hotter countries tend to be less developed. But there&apos;s a deeper, physics-based reason that often gets overlooked:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Thermodynamics silently shapes civilization.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In an isolated system, entropy tends to increase.&lt;br /&gt;
&lt;strong&gt;Heat is energy. Entropy is how spread out and disordered that energy becomes.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hot air = air molecules moving fast&lt;/li&gt;
&lt;li&gt;Cold air = air molecules moving slowly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we add energy to a system, molecules move more freely.&lt;br /&gt;
So &lt;strong&gt;heating cold air&lt;/strong&gt; aligns with entropy. It’s the direction nature already wants to go.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Making air colder = fighting entropy&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Making air hotter = going with entropy&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;In layman’s terms:&lt;br /&gt;
The natural tendency of a room is to let air molecules move faster (get warmer).&lt;br /&gt;
Slowing those molecules down (cooling the room) goes against that tendency and takes continuous effort.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🔧 The Implication&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Cooling a room in a tropical country requires:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Active systems : air conditioning, fans, chilled water, insulation&lt;/li&gt;
&lt;li&gt;Continuous energy input : to maintain a low-entropy (cool) state&lt;/li&gt;
&lt;li&gt;Constant upkeep : heat and humidity wear everything down&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Heating a room in a cold climate can be done passively:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Insulation&lt;/li&gt;
&lt;li&gt;Body heat&lt;/li&gt;
&lt;li&gt;Sunlight&lt;/li&gt;
&lt;li&gt;A single bonfire&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once heat is added, it stays. Keeping warm is relatively easy.&lt;br /&gt;
But cooling down? That needs &lt;strong&gt;machines, electricity, and maintenance&lt;/strong&gt; or you suffer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A poor person in Canada can survive winter with blankets and soup.&lt;br /&gt;
A poor person in a 40°C slum might die from heatstroke.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;🏛️ The Civilization Factor&lt;/h2&gt;
&lt;p&gt;Humans learned to fight cold the moment we discovered fire.&lt;br /&gt;
But we didn’t learn how to fight heat until the &lt;strong&gt;20th century&lt;/strong&gt; with the invention of modern air conditioning.&lt;/p&gt;
&lt;p&gt;In cold climates:&lt;br /&gt;
A cup of tea, a wool blanket, a sealed cabin and you&apos;re fine.&lt;br /&gt;
You decide how hot you want it. Just light the fire.&lt;/p&gt;
&lt;p&gt;In hot climates:&lt;br /&gt;
Even the rivers are warm. There’s no relief.&lt;br /&gt;
It’s &lt;strong&gt;thermodynamic hell&lt;/strong&gt;, and only recently have we had the tools to resist it.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🧠 The Takeaway&lt;/h2&gt;
&lt;p&gt;This isn&apos;t just about comfort. It&apos;s about &lt;strong&gt;survival, labor efficiency, and civilizational momentum&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Hotter regions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Require more energy just to function&lt;/li&gt;
&lt;li&gt;Suffer faster infrastructure decay&lt;/li&gt;
&lt;li&gt;Force people to spend effort &lt;strong&gt;just staying alive&lt;/strong&gt;, not advancing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Heat works against you. Cold simply waits.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Hot countries aren’t behind due to culture or laziness.&lt;br /&gt;
They’re behind because &lt;strong&gt;the physics of heat and entropy made progress harder from the very beginning.&lt;/strong&gt;&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Code is Not Meant to Be Clever</title><link>https://boraxpr.github.io/posts/notclever</link><guid isPermaLink="true">https://boraxpr.github.io/posts/notclever</guid><pubDate>Sun, 08 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lately, I’ve been reflecting on a growing pattern across the frontend ecosystem:&lt;br /&gt;
A push for complexity disguised as innovation.&lt;br /&gt;
A tendency to worship cleverness over clarity.&lt;/p&gt;
&lt;p&gt;And it worries me.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Clarity Over Cleverness&lt;/h2&gt;
&lt;p&gt;In serious environments — where software is expected to last, scale, and evolve — clever code ages poorly.&lt;/p&gt;
&lt;p&gt;It might feel impressive in the moment, but months later that same cleverness becomes friction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When requirements change&lt;/li&gt;
&lt;li&gt;When teams grow&lt;/li&gt;
&lt;li&gt;When someone else has to debug at 2AM&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best code is boring.&lt;br /&gt;
It’s predictable. Readable. Maintainable.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Clever code is for the author. Clear code is for the team.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;TypeScript is Not a Contract&lt;/h2&gt;
&lt;p&gt;TypeScript helps. But it lies.&lt;/p&gt;
&lt;p&gt;It tells you a value is a string — until the API returns &lt;code&gt;null&lt;/code&gt;.&lt;br /&gt;
It says a field exists — until the database changes and nobody updates the types.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;TypeScript is a &lt;strong&gt;developer aid&lt;/strong&gt;, not a runtime guarantee.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some devs push its type system to extremes.&lt;br /&gt;
They build complex type gymnastics that impress nobody outside their GitHub.&lt;/p&gt;
&lt;p&gt;But in real systems, correctness doesn’t come from types.&lt;/p&gt;
&lt;p&gt;It comes from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Validating inputs at runtime&lt;/li&gt;
&lt;li&gt;Enforcing rules where they &lt;strong&gt;actually matter&lt;/strong&gt; — like in the database&lt;/li&gt;
&lt;li&gt;Building flows that are predictable, not fragile&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You don’t need wizard types.&lt;br /&gt;
You need solid boundaries.&lt;/p&gt;
&lt;p&gt;Type safety is a tool. Discipline is the contract.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Abstractions Don’t Make You a Framework Author&lt;/h2&gt;
&lt;p&gt;There’s a growing culture of building wrappers, bundlers, micro-frameworks — and pitching them as “production-ready.”&lt;/p&gt;
&lt;p&gt;But engineering isn’t about abstraction density.&lt;/p&gt;
&lt;p&gt;It’s about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Long-term maintainability&lt;/li&gt;
&lt;li&gt;Upgrade paths&lt;/li&gt;
&lt;li&gt;Operational trade-offs&lt;/li&gt;
&lt;li&gt;Knowing when &lt;em&gt;not&lt;/em&gt; to build something&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Scaffolding a repo is easy.&lt;br /&gt;
Maintaining it across five years of change? That’s the real test.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Code That Lasts&lt;/h2&gt;
&lt;p&gt;Real software survives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Major version upgrades&lt;/li&gt;
&lt;li&gt;Team turnover&lt;/li&gt;
&lt;li&gt;Changing requirements&lt;/li&gt;
&lt;li&gt;Regulatory compliance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That kind of resilience doesn’t come from clever syntax or type wizardry.&lt;br /&gt;
It comes from boring, solid, predictable engineering.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Final Thought&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Engineering is in the thinking — not the typing speed.&lt;br /&gt;
Code is communication. Not a performance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If your goal is to impress future maintainers — not followers —&lt;br /&gt;
Write code like it’ll live longer than you expect.&lt;/p&gt;
&lt;p&gt;Because it probably will.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>[Linux] Fedora 2025: GNOME&apos;s Decline, KDE’s Burden, and the Wayland Gamble</title><link>https://boraxpr.github.io/posts/fedora2025</link><guid isPermaLink="true">https://boraxpr.github.io/posts/fedora2025</guid><pubDate>Sat, 14 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Fedora was one of the go-to distro for people who wanted a clean, minimal setup. It shipped with &lt;a href=&quot;https://www.gnome.org/&quot;&gt;GNOME&lt;/a&gt; as a default desktop environment. Modern, Simple and low-maintenance.&lt;/p&gt;
&lt;p&gt;But &lt;a href=&quot;https://www.gnome.org/&quot;&gt;GNOME&lt;/a&gt; has always carried a big red flag on the forehead: the devs love to lock things down, Playing the Apple™ UX game.
Their vision is making desktop looks and behave like a cheap tablet.&lt;/p&gt;
&lt;p&gt;Thankfully, the open-source community stepped in. &lt;a href=&quot;https://extensions.gnome.org/&quot;&gt;GNOME Extensions&lt;/a&gt; became the lifeline—bridging the gap between GNOME’s locked-down vision and what users actually wanted.
GNOME Extensions are a godsend. They let users take back control—whether that’s adding a proper taskbar, system monitor, or restoring basic functionality GNOME randomly cuts with each release.
When GNOME strips features in the name of “design,” the community patches it back in.&lt;/p&gt;
&lt;p&gt;Fast forward to 2025, things changed. Fedora still ships with GNOME, but now the extensions are buggy, fragile, and frequently broken by upstream updates.
“Just works” turned into “just broke.” Long-time users are fed up. People left.
It&apos;s clear that people fed up with how GNOME has been pushing breaking changes and people just moved to other desktop environment for good.&lt;/p&gt;
&lt;p&gt;At this point, the only sane, usable setup on Fedora is the KDE Spin. It brings back control, flexibility, and a desktop that respects user choice.&lt;/p&gt;
&lt;p&gt;But even Fedora KDE Spin still comes with a big caution: Wayland.&lt;/p&gt;
&lt;p&gt;Wayland is supposed to be the next-generation replacement for X11—the old display server that’s powered Linux desktops for decades.
In theory, Wayland offers a cleaner design, better security, and more efficient rendering.
In reality? It has been &quot;THE FUTURE&quot; since 2008. In 2021, I remember wrestling with wayland glitch that cause my desktop total stuck.
Today, It’s still not ready for prime time in 2025, especially if you’re a gamer, developer, or anyone who needs reliable desktop tooling.&lt;/p&gt;
&lt;p&gt;Yesterday, I launched Stellar Blade on my machine—and the performance was a stuttery mess. I switched to GE-Proton, the go-to custom Proton build for better compatibility. Still stuttered.
After troubleshooting, the culprit was obvious: Wayland.&lt;/p&gt;
&lt;p&gt;Gaming on Wayland is mostly fine until you hit that single game for me it&apos;s Stellar Blade where Frame pacing is inconsistent, and input lag is noticeable.
But it’s not just about games—even basic apps like Chrome behave weirdly. UI elements misalign, invisible buttons appear, clicks land in the wrong place, and windows sometimes act like they’re half-rendered.
It’s not just inconvenient—it’s disorienting. Sometimes, If It even stuck at &lt;a href=&quot;https://github.com/sddm/sddm&quot;&gt;sddm&lt;/a&gt;.
When your daily browser becomes a glitchy experience, that’s a red flag that the desktop stack isn’t production-ready.&lt;/p&gt;
&lt;p&gt;After I dig deep, it turns out that some apps or game still based hard on X11. But first I&apos;m going to visualize the &quot;Linux Desktop Stack&quot; and what they are composed of.
Unlike windows or mac where it&apos;s a blackbox like so.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌──────────────────────────┐
│       Graphical App      │   ← Chrome, Photoshop, Teams
└────────────┬─────────────┘
             │
┌────────────▼─────────────┐
│     Operating System     │   ← Win32, DWM, Quartz, Audio, Input, GPU stack
│    (monolithic, hidden)  │
└────────────┬─────────────┘
             │
┌────────────▼─────────────┐
│        Hardware          │   ← CPU, GPU, Display, Audio, etc.
└──────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Modern Linux Desktop Stack:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌────────────────────────────────────────────────────┐
│                  Graphical Applications            │
│   (Chrome, Firefox, VSCode, Steam, etc.)           │
└────────────────────────────────────────────────────┘
               ▲              ▲             ▲
               │              │             │
┌──────────────┴──────┐ ┌─────┴─────────┐ ┌──┴────────────┐
│  GUI Toolkits       │ │  Wayland/X11  │ │  Audio System │
│ (Qt, GTK, Electron) │ │  Client APIs  │ │ (PipeWire)    │
└────────────┬────────┘ └────┬──────────┘ └────┬──────────┘
             │               │                 │
┌────────────▼────────────┐  │                 │
│  Window Manager /       │  │                 │
│  Compositor (KWin,      │  │                 │
│  Mutter, wlroots, etc.) │  │                 │
└────────────┬────────────┘  │                 │
             │               │                 │
┌────────────▼───────────────▼─────────────────▼────────┐
│              Display Server Protocol (Wayland / X11)  │
└───────────────────────────────────────────────────────┘
                           │
              ┌────────────▼────────────┐
              │       Kernel (DRM/KMS)  │
              │     Input &amp;amp; GPU drivers │
              └────────────┬────────────┘
                           │
              ┌────────────▼────────────┐
              │        Hardware         │
              └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;There is no true non-moving part on Linux, you can change anything but it comes with bugs if they are not designed with that specific combination integration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As for Fedora KDE Spin, the non-moving parts are WM (KWin) + Display Server (Wayland) + NVIDIA PROPRIETARY DRIVER.
The problem is that while Fedora pushes Wayland as a hard default, There are multiple apps that are not yet built to use Wayland Client APIs that means they still use X11.
Now Wayland solves that problem by providing XWayland APIs aims to support these apps and fall them back on to X11. This makes it&apos;s possible to run X11 apps on Wayland without crashing.
The point is not crashing does not mean no problems. It introduces mismatch of X11 legacy scaling, rendering, gpu connectivity quirks within the wayland environment itself.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./image4.png&quot; alt=&quot;chrome x11 jank on fedora kde spin&quot; /&gt;
The problem here is Google Chrome on &lt;a href=&quot;https://www.geeksforgeeks.org/linux-unix/how-to-use-the-rpm-command-in-linux/&quot;&gt;Red Hat Package Manager&lt;/a&gt; still ship with X11 as a default while Fedora already moves to Wayland as a default. So when I install google chrome on fedora, It falls back to X11 (XWayland) and causes problem like UI and screen mismatch on Multi-monitor setups. Whenever I click fullscreen, there is 75% chance the UI and the reality are going to be mismatch e.g. the UI show button is there but when i click : actual button is 5px downward.&lt;/p&gt;
&lt;h2&gt;The Fix&lt;/h2&gt;
&lt;p&gt;Specifically for Chrome, ~/.local/share/applications/google-chrome.desktop must be modified to be launched with flags to make Chrome uses Wayland as a Backend.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Exec=/usr/bin/google-chrome-stable --ozone-platform=wayland --enable-features=WaylandWindowDecorations %U
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The fact that this even works mean Google Chrome already supports Wayland but they don&apos;t rollout with Wayland as defaults. This config will be overwritten anytimes there is package update so I must copy and create another launcher for Chrome itself. oh. Fedora experience is almost like Arch Linux in 2025 : I installed Default flavor - Met Unusable Gnome Extensions, buggy even caused multiple crashes. I manually installed KDE - now multiple Desktop managers setup is buggy GNOME conflicts with KDE. I reinstalled anew with KDE Spin. Now I meet Wayland-X11-XWayland-Nvidia messes. Good thing that there are still way out but Fedora in 2025 is not the same 2021 Fedora that it just works.&lt;/p&gt;
&lt;p&gt;Now we&apos;re in the limbo. KDE+Wayland+NVIDIA GPU = Abysmal performance on some games, Visual Glitches on Google Chrome unless force launch flag to use Wayland, etc. While KDE+X11+NVIDIA GPU = Abysmal Desktop Experience because KWIN Compositor are not playing well with X11 due to de-prioritized and focused on wayland.&lt;/p&gt;
&lt;p&gt;Fedora has become the distro where everything is possible — and nothing is guaranteed. If 2021 was the “just works” era, 2025 is the “just fix it yourself” generation. Back to finding way to run Stellar Blade on Wayland without lagging hard.&lt;/p&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GNOME on Fedora is now fragile and over-simplified.&lt;/li&gt;
&lt;li&gt;KDE Spin is better — but Wayland+NVIDIA still cause random graphical glitches.&lt;/li&gt;
&lt;li&gt;Chrome defaults to X11 via XWayland = misaligned UI, broken fullscreen.&lt;/li&gt;
&lt;li&gt;Manual &lt;code&gt;.desktop&lt;/code&gt; fixes help, but updates overwrite them.&lt;/li&gt;
&lt;li&gt;Fedora today is bleeding-edge in the worst way.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><author>Boraxpr</author></item><item><title>AI แทนคนไทยไม่ได้หรอกครับ</title><link>https://boraxpr.github.io/posts/thaiaicontext</link><guid isPermaLink="true">https://boraxpr.github.io/posts/thaiaicontext</guid><pubDate>Sat, 01 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;ทุกคนพูดถึง AI กำลังจะทดแทนงานต่างๆ&lt;br /&gt;
โอเค มันอาจจะฟังดู make sense ถ้าคุณฟังแต่ feed ตาม social หรือแม้แต่ตาม conference&lt;br /&gt;
ในไทยที่ชอบพูดกันว่า “อีกหน่อยหุ่นยนต์จะมาแทนคน”&lt;/p&gt;
&lt;p&gt;แต่ถ้าเรานั่งคิดจริงๆ ในเชิงสมการเศรษฐกิจ&lt;br /&gt;
**ในบริบทของประเทศไทย มัน make sense เหรอครับ?  **&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;ค่าแรงคนไทยโดยเฉลี่ยวันละหลักร้อย&lt;br /&gt;
หุ่นยนต์โดยเฉลี่ยตัวละหลักครึ่งล้าน&lt;br /&gt;
คนไทยทำงานทั้งปี ได้แค่แขนหุ่นยนต์ข้างเดียว&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;ในประเทศพัฒนาแล้วอย่างสหรัฐฯ หรือยุโรป ค่าแรงเฉลี่ยวันละ 5,000 บาทขึ้นไป&lt;br /&gt;
หุ่นยนต์หนึ่งตัวราคา 600,000-1,000,000 บาท มันจึงพอคำนวณ ROI ได้ ถ้าใช้งานแทนแรงงาน 24 ชั่วโมงโดยไม่หยุด&lt;/p&gt;
&lt;p&gt;แต่ในไทย ค่าแรงเฉลี่ยแค่ 300–400 บาทต่อวัน&lt;br /&gt;
แปลว่าหุ่นยนต์หนึ่งตัวต้องทำงานแทนคน เกือบ 10 ปีเต็ม ถึงจะคุ้มทุน&lt;br /&gt;
และนั่นยังไม่รวม **ค่า maintenance, ค่าไฟ, ค่าซ่อม, downtime, และค่าเทรนคนให้ใช้มันได้ **
และนี่ยังไม่รวม &lt;strong&gt;คุณภาพงาน (quality)&lt;/strong&gt; ที่เสียไปอีก&lt;br /&gt;
อย่างล่าสุด McDonald’s ในตะวันตกที่ลงทุนกับ AI Drive-Thru ก็ต้องพับโปรเจกต์ทิ้ง&lt;br /&gt;
หลังลูกค้าร้องเรียนจำนวนมากจากการสั่งผิดพลาด (https://www.bbc.com/news/articles/c722gne7qngo)&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;AI หรือ automation จึงไม่ใช่ปัญหาสำหรับประเทศที่แรงงานถูก&lt;br /&gt;
แต่กลับเป็นปัญหาของประเทศที่แรงงานแพงต่างหาก&lt;br /&gt;
เพราะ “ค่าแรงไทย” มันยังถูกเกินกว่าที่เทคโนโลยีจะเข้ามาแทนได้อย่างคุ้มจริง&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;ในประเทศที่ค่าแรงยังถูก&lt;br /&gt;
สิ่งที่ต้องลงทุนไม่ใช่ “หุ่นยนต์”&lt;br /&gt;
แต่คือ “สมองที่รู้จักใช้หุ่นยนต์ให้เกิดประโยชน์”&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Damage Absorber: One Year of Senior Engineering Under a Non-Tech Power Structure</title><link>https://boraxpr.github.io/posts/damageabsorber</link><guid isPermaLink="true">https://boraxpr.github.io/posts/damageabsorber</guid><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When you start your career, you think software engineering is about code.&lt;br /&gt;
You chase clean patterns, perfect programming languages, the right framework, the right naming, the right architecture diagrams.&lt;br /&gt;
It feels like the quality of the system depends on how good you write code.&lt;/p&gt;
&lt;p&gt;Then you get promoted.&lt;br /&gt;
You move closer to the decision making layer.&lt;br /&gt;
That is the moment you learn the truth.&lt;/p&gt;
&lt;p&gt;Code is never the main problem.&lt;br /&gt;
The real problem is power.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;1. Junior engineers solve technical problems. Senior engineers absorb organizational damage.&lt;/h3&gt;
&lt;p&gt;As a junior, the hardest thing you face is a tricky bug or a messy module.&lt;/p&gt;
&lt;p&gt;As a senior, you start taking hits from every direction.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Last minute business changes&lt;/li&gt;
&lt;li&gt;Fake deadlines&lt;/li&gt;
&lt;li&gt;Requirement shifts with no context&lt;/li&gt;
&lt;li&gt;Scope creep driven by pressure, not logic&lt;/li&gt;
&lt;li&gt;Misaligned incentives&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You are no longer judged by code quality, but by how well you can protect the team from chaos above you.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. The real system is not the backend or the frontend. The real system is the hierarchy.&lt;/h3&gt;
&lt;p&gt;Software architecture in many companies is just a decoration.&lt;br /&gt;
The real architecture is the power flow of the organization.&lt;/p&gt;
&lt;p&gt;If business holds full power, engineering becomes a service desk.&lt;br /&gt;
If architecture has no authority, design becomes optional.&lt;br /&gt;
If KPIs reward speed over correctness, technical debt becomes cultural.&lt;/p&gt;
&lt;p&gt;And when this happens, seniors turn into firefighters.&lt;br /&gt;
Not designers. Not builders.&lt;br /&gt;
Just human buffers between unreasonable demands and a collapsing reality.&lt;/p&gt;
&lt;p&gt;Being part of an architecture team forced me to move across business, infra, dev, and AI groups.&lt;br /&gt;
Seeing how decisions flow between these layers made it clear that the real problems rarely start in the codebase.&lt;br /&gt;
They start in the structure above it, long before engineers ever touch a keyboard.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. Speed-driven cultures destroy their best engineers first.&lt;/h3&gt;
&lt;p&gt;I was officially promoted only two months ago, but I had already been working at the senior level for almost a year.&lt;br /&gt;
That gap between responsibility and title is common in non-tech organizations, and it shapes how you see the system.&lt;br /&gt;
You learn the role long before anyone calls it by name.&lt;/p&gt;
&lt;p&gt;When every project is “urgent”, nothing has value anymore.&lt;/p&gt;
&lt;p&gt;You see smart engineers slowly losing their edge.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They stop thinking long term&lt;/li&gt;
&lt;li&gt;They stop pushing back&lt;/li&gt;
&lt;li&gt;They stop designing&lt;/li&gt;
&lt;li&gt;They start rushing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And after enough cycles, their skill fades.&lt;br /&gt;
Not because they are bad, but because the system forces them to operate below their ability.&lt;/p&gt;
&lt;p&gt;This is how organizations waste talent.&lt;br /&gt;
Not by lacking resources, but by making speed the only metric that matters.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4. Senior engineering is not about knowing everything. It is about knowing what decisions to refuse.&lt;/h3&gt;
&lt;p&gt;A senior who cannot say no is a technician with extra meetings.&lt;/p&gt;
&lt;p&gt;Good engineers do not save projects by writing faster code.&lt;br /&gt;
They save projects by preventing bad directions from turning into irreversible failures.&lt;/p&gt;
&lt;p&gt;But that only works if the organization respects reasoning.&lt;br /&gt;
If not, seniors become damage absorbers.&lt;br /&gt;
They protect the company from its own decisions until they burn out.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5. The higher you go, the more you see that the codebase is a reflection of the power structure.&lt;/h3&gt;
&lt;p&gt;Bad code is rarely caused by incompetence.&lt;br /&gt;
It is caused by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rushed timelines&lt;/li&gt;
&lt;li&gt;poor alignment&lt;/li&gt;
&lt;li&gt;unclear ownership&lt;/li&gt;
&lt;li&gt;politics&lt;/li&gt;
&lt;li&gt;mismanaged expectations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most senior engineers spend more time taming the system around the code than the code itself.&lt;/p&gt;
&lt;p&gt;And that is the ugly truth nobody tells juniors.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;One year at the senior level taught me more about organizations than technology.&lt;/p&gt;
&lt;p&gt;I learned that code is the easy part.&lt;br /&gt;
The hard part is navigating decisions made by people who never see the technical impact of their choices.&lt;/p&gt;
&lt;p&gt;In healthy companies, senior engineers guide the direction.&lt;br /&gt;
In unhealthy ones, senior engineers shield the team from a storm that never stops.&lt;/p&gt;
&lt;p&gt;If you want to grow, learn the tech.&lt;br /&gt;
If you want to survive, learn the system.&lt;br /&gt;
If you want to thrive, choose where you work as carefully as you choose your tools.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Digital Manual: Thailand’s workflow landscape and why we will not see AI adoption at the level of the US</title><link>https://boraxpr.github.io/posts/digitalmanual</link><guid isPermaLink="true">https://boraxpr.github.io/posts/digitalmanual</guid><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Let’s be honest. Thailand’s workflow landscape is nowhere near ready for the kind of AI-driven transformation we see in the United States. The problem is not complicated. Our systems are still stuck in a “digital manual” era, where paper has simply been converted into files, but the processes behind those files were never redesigned for real automation.&lt;/p&gt;
&lt;p&gt;The US built its foundations differently. Data pipelines, APIs, centralized systems, standardized processes. When AI arrived, it plugged into workflows that were already designed for machines. Replacing human labor became straightforward.&lt;/p&gt;
&lt;p&gt;Thailand never built those foundations, and here is why.&lt;/p&gt;
&lt;h2&gt;1. Digital manual is not digital automation&lt;/h2&gt;
&lt;p&gt;Most Thai organizations still follow their old manual workflows, just with Excel and PDF instead of paper.&lt;br /&gt;
Data is entered by hand with no validation, no schema, no automated checks.&lt;br /&gt;
Every step still needs a person to click, sign, forward, and approve.&lt;br /&gt;
AI cannot replace humans when humans remain the glue that keeps the workflow alive.&lt;/p&gt;
&lt;h2&gt;2. Fragmented data with no standards&lt;/h2&gt;
&lt;p&gt;The US has invested heavily in mature data pipelines.&lt;br /&gt;
Thailand stores data based on personal habits.&lt;br /&gt;
Files with identical names but different structures.&lt;br /&gt;
PDF scans mixed with photos taken on mobile phones.&lt;br /&gt;
Duplicate data, missing data, and fields filled only to make forms “pass”.&lt;br /&gt;
AI ends up drowning in noise before it finds anything useful.&lt;/p&gt;
&lt;h2&gt;3. Legacy systems that cannot be extended&lt;/h2&gt;
&lt;p&gt;Many organizations still run systems built more than a decade ago.&lt;br /&gt;
Some have no API.&lt;br /&gt;
Some rely on code no one dares to touch.&lt;br /&gt;
These environments cannot support AI, because AI requires continuous workflow integration and automated data access.&lt;br /&gt;
In Thailand, the rule is simple: “Don’t touch it or it breaks.”&lt;/p&gt;
&lt;h2&gt;4. AI needs clear processes, but Thailand relies on people&lt;/h2&gt;
&lt;p&gt;The US has well-defined SOPs.&lt;br /&gt;
Thailand relies on individual experience.&lt;br /&gt;
Two employees handling the same task often follow two different methods.&lt;br /&gt;
AI cannot work with this level of variability, because the underlying process is not deterministic.&lt;/p&gt;
&lt;h2&gt;5. Decisions depend on relationships, not systems&lt;/h2&gt;
&lt;p&gt;Many Thai workflows depend on who calls whom, who signs what, who knows the right person.&lt;br /&gt;
These are inherently human-driven steps that AI cannot replace.&lt;br /&gt;
The US removed this dependency long ago by shifting trust to systems instead of individuals.&lt;/p&gt;
&lt;h2&gt;6. AI cannot replace people when people spend their time fixing broken systems&lt;/h2&gt;
&lt;p&gt;In many Thai workplaces, employees spend more time “fixing the system” than using it.&lt;br /&gt;
Automations break.&lt;br /&gt;
Data is wrong.&lt;br /&gt;
Forms fail.&lt;br /&gt;
Servers crash.&lt;br /&gt;
People work around problems manually.&lt;br /&gt;
Expecting AI to replace jobs in this environment is pure fantasy.&lt;/p&gt;
&lt;h2&gt;7. Thailand confuses using files with being digital&lt;/h2&gt;
&lt;p&gt;This is the core misunderstanding.&lt;br /&gt;
Many organizations believe they are digital because they use documents in electronic form.&lt;br /&gt;
In reality, this is still digital manual.&lt;br /&gt;
No automation.&lt;br /&gt;
No workflow engines.&lt;br /&gt;
No pipelines.&lt;br /&gt;
No orchestration.&lt;br /&gt;
AI has nothing to integrate with because the process is not a system, it is just files moving around.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;AI will only replace labor in Thailand when the entire workflow landscape is rebuilt.&lt;br /&gt;
Buying AI tools will not magically automate anything.&lt;br /&gt;
The US redesigned its foundations decades ago.&lt;br /&gt;
Thailand only started cleaning up Excel sheets yesterday.&lt;/p&gt;
&lt;p&gt;This is why we will not see AI-driven workforce reduction at the US scale anytime soon.&lt;br /&gt;
The country still depends on people to support systems that were never designed for automation.&lt;/p&gt;
&lt;p&gt;Before AI can work, Thailand needs real digital automation, not digital manual wrapped in a modern façade.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Bodyshop: Thai Software Job Market Landscape</title><link>https://boraxpr.github.io/posts/thaildigitallandscape</link><guid isPermaLink="true">https://boraxpr.github.io/posts/thaildigitallandscape</guid><pubDate>Sun, 23 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Most people talk about the tech industry in Thailand as if it works like the United States.&lt;br /&gt;
It does not.&lt;br /&gt;
The Thai software market is built on a foundation that almost guarantees shallow work, unstable careers, and limited long term growth.&lt;/p&gt;
&lt;p&gt;The reason is simple.&lt;br /&gt;
Our market is not driven by product companies.&lt;br /&gt;
It is driven by bodyshops.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. The market is dominated by contractors, subs, and outsourced teams&lt;/h2&gt;
&lt;p&gt;When a country has more contracting firms than product companies, the incentive structure flips completely.&lt;/p&gt;
&lt;p&gt;Product companies build.&lt;br /&gt;
Bodyshops bill.&lt;/p&gt;
&lt;p&gt;One cares about long term capability.&lt;br /&gt;
The other cares about man hours.&lt;/p&gt;
&lt;p&gt;This shapes everything in the market.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Juniors are cheap labor&lt;/li&gt;
&lt;li&gt;Seniors are expensive labor&lt;/li&gt;
&lt;li&gt;Training is seen as cost&lt;/li&gt;
&lt;li&gt;Stability is rare&lt;/li&gt;
&lt;li&gt;Skill progression depends on luck, not structure&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most engineers in Thailand do not grow because the system is not designed for their growth at all.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. Most devs work for the client, not the company on their payroll&lt;/h2&gt;
&lt;p&gt;Bodyshops put you inside a client site, then the client drives your workload, your stress, your timeline, your pressure.&lt;/p&gt;
&lt;p&gt;So who do you belong to?&lt;br /&gt;
Your employer?&lt;br /&gt;
Your client?&lt;br /&gt;
Neither.&lt;br /&gt;
You become a floating worker with no home and no real identity.&lt;/p&gt;
&lt;p&gt;This is why turnover is high.&lt;br /&gt;
You cannot build culture or craft when engineers are treated like replaceable parts.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. Skill depth is low because nobody owns the product&lt;/h2&gt;
&lt;p&gt;A product team wants people who understand the system deeply.&lt;br /&gt;
A bodyshop team wants people who can be swapped easily.&lt;/p&gt;
&lt;p&gt;The result is a landscape full of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;quick deliverables&lt;/li&gt;
&lt;li&gt;shallow code&lt;/li&gt;
&lt;li&gt;minimal architecture&lt;/li&gt;
&lt;li&gt;high pressure&lt;/li&gt;
&lt;li&gt;low ownership&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Engineers write code, but rarely build systems.&lt;br /&gt;
This prevents the market from producing strong mid to senior engineers in large volumes.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Promotion in a bodyshop market is not based on skill&lt;/h2&gt;
&lt;p&gt;It is based on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how billable you are&lt;/li&gt;
&lt;li&gt;how fast you deliver&lt;/li&gt;
&lt;li&gt;how much margin you generate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not whether you think well, design well, or understand systems.&lt;/p&gt;
&lt;p&gt;That is why many so called seniors are actually juniors with more years, not more depth.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. The market punishes those who want to grow beyond coding&lt;/h2&gt;
&lt;p&gt;If you think in terms of systems, incentives, architecture, or power structure, you are already above the local average.&lt;/p&gt;
&lt;p&gt;But the market is slow to reward it.&lt;br /&gt;
Because the market is not built around product sophistication.&lt;/p&gt;
&lt;p&gt;It is built around headcount reselling.&lt;/p&gt;
&lt;p&gt;That is why deep thinkers feel like a minority.&lt;br /&gt;
And they are.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;6. Why this matters&lt;/h2&gt;
&lt;p&gt;If Thailand wants strong engineers, we need more product companies and fewer bodyshops.&lt;br /&gt;
We need incentives that reward long term thinking, not quick labor rental.&lt;/p&gt;
&lt;p&gt;Until then, the job landscape will stay the same.&lt;/p&gt;
&lt;p&gt;Most engineers will be stuck in shallow work.&lt;br /&gt;
Only a small percentage will break out by entering product companies, global companies, or tech first environments.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The Thai software market is not broken.&lt;br /&gt;
It is simply built differently.&lt;br /&gt;
It rewards the wrong behaviors and punishes long term thinking.&lt;/p&gt;
&lt;p&gt;If you want to grow, you must choose environments that let you build rather than environments that rent you out.&lt;/p&gt;
&lt;p&gt;The market will not change soon.&lt;br /&gt;
But your path can.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Atomicity is not magic</title><link>https://boraxpr.github.io/posts/atomicity</link><guid isPermaLink="true">https://boraxpr.github.io/posts/atomicity</guid><pubDate>Sat, 29 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;./image-2.png&quot; alt=&quot;aciddb&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;image from : https://www.scylladb.com/glossary/acid-database/&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CS courses love to say “RDBMS gives you atomicity.”&lt;br /&gt;
Yeah, no. That’s the classroom version.&lt;/p&gt;
&lt;p&gt;In reality, atomicity is not magic. It’s a fragile outcome created by a bunch of lower-level components doing the right thing at the right time. Miss one, and the whole idea falls apart.&lt;/p&gt;
&lt;p&gt;Atomicity only holds because of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;write-ahead logging&lt;/li&gt;
&lt;li&gt;strict write ordering&lt;/li&gt;
&lt;li&gt;real fsync behavior&lt;/li&gt;
&lt;li&gt;crash-consistent metadata updates&lt;/li&gt;
&lt;li&gt;durable page flushing&lt;/li&gt;
&lt;li&gt;atomic rename semantics&lt;/li&gt;
&lt;li&gt;predictable disk guarantees&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Break any of these and atomicity is gone.&lt;br /&gt;
Run a database on fake-POSIX storage like SMB or Azure Files and you’ll see how quickly things go sideways.&lt;/p&gt;
&lt;p&gt;RDBMS doesn’t “provide” atomicity.&lt;br /&gt;
It depends on the filesystem being honest, consistent, and actually durable.&lt;/p&gt;
&lt;p&gt;If the disk lies, atomicity dies.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Understanding Why Azure File Share Fails Under Heavy Linux File Operations</title><link>https://boraxpr.github.io/posts/azurefileshareonlinuxworkload</link><guid isPermaLink="true">https://boraxpr.github.io/posts/azurefileshareonlinuxworkload</guid><pubDate>Sat, 29 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Why Azure File Share breaks TSDB/WAL workloads (SMB and NFS)&lt;/h2&gt;
&lt;p&gt;Azure File Share is built on top of a &lt;strong&gt;Windows-based backend&lt;/strong&gt;. This matters because Windows and Linux have &lt;strong&gt;fundamentally different filesystem semantics&lt;/strong&gt;, especially around atomic operations and metadata consistency.&lt;/p&gt;
&lt;p&gt;If you only &lt;strong&gt;read/write small files&lt;/strong&gt;, you won&apos;t notice the difference.
The problems appear when you do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;massive writes&lt;/li&gt;
&lt;li&gt;rapid rename/delete&lt;/li&gt;
&lt;li&gt;concurrent writes&lt;/li&gt;
&lt;li&gt;database-style workloads&lt;/li&gt;
&lt;li&gt;TSDB/WAL workloads&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;WAL = Write-Ahead Log used by Prometheus TSDB, Loki (Single binary/local mode), Postgres DB, Other reliable databases. It is used for making ingestion resilient: if the service crashes, data is not lost.
&lt;a href=&quot;https://www.postgresql.org/docs/current/wal-intro.html&quot;&gt;Read more&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is where Azure File Share fails.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Azure File Share Protocols&lt;/h2&gt;
&lt;p&gt;Azure File Share offers two ways to mount storage:&lt;/p&gt;
&lt;h3&gt;1. &lt;strong&gt;SMB&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Native Windows behavior&lt;/li&gt;
&lt;li&gt;NTFS ACLs&lt;/li&gt;
&lt;li&gt;Zero POSIX semantics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Completely unsuitable for Linux apps requiring atomicity&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. &lt;strong&gt;NFS (Azure Files NFSv4.1)&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Document claims “Fully POSIX”&lt;/li&gt;
&lt;li&gt;But the limitation section states clearly:
&lt;strong&gt;“ACLs aren’t supported.”&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the key problem.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;What ACL Means (Real POSIX vs Fake POSIX)&lt;/h2&gt;
&lt;p&gt;People think POSIX = &lt;code&gt;rwxrwxrwx&lt;/code&gt;
But POSIX also includes &lt;strong&gt;ACL (Access Control List)&lt;/strong&gt; support for fine-grained permissions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# file: notes.txt
# owner: tar
# group: devs
user::rw-
user:bob:rw-
group::r--
group:design:r--
mask::rw-
other::---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Azure NFS does &lt;strong&gt;not&lt;/strong&gt; support these.
No NFSv4 ACLs.
Only rwx bits.
This means Azure NFS is &lt;strong&gt;POSIX only on the surface&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Under the hood:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Linux App (Container)
      ↓
POSIX-like NFS Emulation Layer
      ↓
Azure File Backend (Windows ACL Logic)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a &lt;strong&gt;translation layer&lt;/strong&gt;.
Translation = inconsistency = bugs.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Why TSDB, WAL, Prometheus, Loki break&lt;/h2&gt;
&lt;p&gt;It’s not “lack of ACL” itself that causes corruption.
It’s what that &lt;em&gt;implies&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Azure NFS is not backed by a true POSIX filesystem.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This leads to:&lt;/p&gt;
&lt;h3&gt;1. &lt;strong&gt;Non-atomic rename/delete&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Linux guarantees atomicity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rename: instant old→new&lt;/li&gt;
&lt;li&gt;delete: instantly gone&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Windows needs multiple steps (temp file, move, commit).
TSDB workloads rely heavily on atomic rename/delete for WAL and index files.
Non-atomic operations cause partial files and corruption.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. &lt;strong&gt;Metadata drift&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Real POSIX filesystems store strong metadata in &lt;strong&gt;inodes&lt;/strong&gt;, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;owner&lt;/li&gt;
&lt;li&gt;group&lt;/li&gt;
&lt;li&gt;permissions&lt;/li&gt;
&lt;li&gt;file size&lt;/li&gt;
&lt;li&gt;last modified/accessed&lt;/li&gt;
&lt;li&gt;block pointers&lt;/li&gt;
&lt;li&gt;hardlinks&lt;/li&gt;
&lt;li&gt;inode number&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Databases depend on these for correctness.&lt;/p&gt;
&lt;p&gt;Azure File NFS uses backend ACL logic (Windows-style), so inode metadata is &lt;strong&gt;emulated&lt;/strong&gt; and can drift.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. &lt;strong&gt;Inode instability&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Prometheus maintainers found inode drift on Azure File.
This causes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;duplicate inodes&lt;/li&gt;
&lt;li&gt;stale filehandles&lt;/li&gt;
&lt;li&gt;corrupted index blocks&lt;/li&gt;
&lt;li&gt;WAL segment corruption&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reference:
&lt;a href=&quot;https://github.com/prometheus/prometheus/issues/10679&quot;&gt;https://github.com/prometheus/prometheus/issues/10679&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4. &lt;strong&gt;Latency in metadata operations&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Azure File NFS metadata latency is &lt;strong&gt;high single-digit milliseconds&lt;/strong&gt;.
TSDBs expect &lt;strong&gt;microseconds&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;High-latency metadata = race conditions.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5. &lt;strong&gt;Not suitable for databases at all&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This affects not just Loki/Prometheus, but also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;MSSQL&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;Any ACID database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s the reason &lt;strong&gt;data centers use Linux filesystems&lt;/strong&gt; (xfs/ext4) for database storage.
Linux guarantees atomicity.
Windows-like filesystems do not.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Final Summary&lt;/h2&gt;
&lt;p&gt;Azure File Share:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SMB uses Windows filesystem semantics,&lt;/li&gt;
&lt;li&gt;NFSv4.1 is only a POSIX &lt;em&gt;emulation&lt;/em&gt; layer,&lt;/li&gt;
&lt;li&gt;Backend permissions logic is Windows ACL based,&lt;/li&gt;
&lt;li&gt;Atomicity, metadata, and inode behavior do not match real Linux filesystems,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which means it &lt;strong&gt;cannot guarantee consistency&lt;/strong&gt; for workloads that rely on strict POSIX guarantees.&lt;/p&gt;
&lt;p&gt;This is exactly why corruption eventually shows up under:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TSDB workloads (Prometheus, Loki)&lt;/li&gt;
&lt;li&gt;WAL-heavy systems&lt;/li&gt;
&lt;li&gt;database workloads&lt;/li&gt;
&lt;li&gt;anything doing rapid rename/delete cycles&lt;/li&gt;
&lt;li&gt;anything depending on strong inode semantics&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TLDR&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Do not use Azure File Share (SMB or NFS) for databases, TSDB, WAL, or any index-heavy workload.&lt;br /&gt;
Use a strict POSIX-compliant block device instead.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On Azure, that means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Azure Managed Disks via &lt;code&gt;managed-csi&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ext4 or xfs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ReadWriteOnce (single node)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guaranteed POSIX atomicity and metadata stability&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Azure File Share fakes POSIX at the protocol layer but is backed by Windows ACL semantics.&lt;br /&gt;
That translation introduces nondeterministic behaviors under load.&lt;br /&gt;
This is not a throughput problem, it is a correctness problem.&lt;/p&gt;
&lt;p&gt;Workloads that require &lt;em&gt;real&lt;/em&gt; Linux filesystem guarantees include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus TSDB&lt;/li&gt;
&lt;li&gt;Loki local storage&lt;/li&gt;
&lt;li&gt;Postgres, MySQL&lt;/li&gt;
&lt;li&gt;Redis with persistence&lt;/li&gt;
&lt;li&gt;Any ACID database&lt;/li&gt;
&lt;li&gt;Any component that uses WAL or atomic rename/delete&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your workload cares about data integrity, you must run it on &lt;strong&gt;real disk&lt;/strong&gt;, not network-emulated POSIX.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Someone Told Me ‘Just Add Cache’, Here’s What Actually Happened</title><link>https://boraxpr.github.io/posts/justcacheit</link><guid isPermaLink="true">https://boraxpr.github.io/posts/justcacheit</guid><pubDate>Sat, 29 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;./image-4.png&quot; alt=&quot;REDIS&quot; /&gt;
In this era, it’s incredibly easy to take a wrong turn. Large language models answer with confidence, and that confidence tends to spill into human conversations. People, regardless of their actual experience, can end up suggesting architectural decisions they aren’t equipped to evaluate. “Just add cache” is one of the most common oversimplifications.&lt;/p&gt;
&lt;p&gt;We’re running an application with multiple instances on Kubernetes, and like everyone else who has done horizontal scaling, we have Redis as a shared component.&lt;/p&gt;
&lt;p&gt;A while ago, I used to think Redis was a universal speed booster.
It’s RAM, it’s fast, it must make everything faster. Right?&lt;/p&gt;
&lt;p&gt;Not quite.&lt;/p&gt;
&lt;p&gt;Redis doesn’t magically lower latency. Redis doesn’t fix poorly shaped data. Redis doesn’t improve performance if the root problem is upstream. In most real systems, Redis is used to keep distributed instances in sync and reduce repeated heavy work, not as a silver bullet for slowness.&lt;/p&gt;
&lt;p&gt;And this is where the misconception hits hardest.&lt;/p&gt;
&lt;p&gt;If your JSON payload is massive, especially when it crosses into multi-MB territory, pushing it into Redis won’t save you. You aren’t reducing cost, you’re just relocating it. The biggest penalty stops being storage access, and becomes the unavoidable JSON.parse overhead in your application.&lt;/p&gt;
&lt;p&gt;Parsing a huge structure costs far more CPU time than whatever micro-latency Redis saves by being in RAM. You trade one bottleneck for another, and the system doesn’t actually get faster. It can even get slower due to network overhead, replication load, memory pressure, and throughput degradation.&lt;/p&gt;
&lt;p&gt;In short, caching works when the data is small, stable, and cheap to serialize.
Caching giant blobs is not optimization, it’s misdirection.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>The “Just Use X” Fallacy</title><link>https://boraxpr.github.io/posts/justusemagicx</link><guid isPermaLink="true">https://boraxpr.github.io/posts/justusemagicx</guid><pubDate>Thu, 18 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In modern engineering discussions, complex problems are often reduced to simple prescriptions.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Just use AI.”&lt;br /&gt;
“Just add cache.”&lt;br /&gt;
“Just switch the language.”&lt;br /&gt;
“Just change the framework.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Different words. Same pattern.&lt;/p&gt;
&lt;p&gt;This kind of thinking is not optimization.&lt;br /&gt;
It is avoidance.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Why “Just Use X” sounds convincing&lt;/h2&gt;
&lt;p&gt;“Just use X” feels efficient. It suggests decisiveness and competence without requiring a deep explanation. The listener is spared the discomfort of uncertainty, trade-offs, and messy constraints.&lt;/p&gt;
&lt;p&gt;When such statements come from people with perceived authority, seniority, reputation, or even from AI systems that speak with confidence, they spread easily. The idea gains momentum not because it is correct, but because it feels complete.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;AI amplifies shallow reasoning&lt;/h2&gt;
&lt;p&gt;Large language models do not reason about problems in the way humans expect them to. They respond to the structure and assumptions embedded in a prompt.&lt;/p&gt;
&lt;p&gt;If a question assumes that a problem is simple and solvable by a single tool, the answer will often reinforce that assumption. Not maliciously, but fluently.&lt;/p&gt;
&lt;p&gt;The result is subtle but dangerous. Weak mental models are not challenged. They are refined, polished, and made more persuasive.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Tools do not remove cost, they move it&lt;/h2&gt;
&lt;p&gt;There is no such thing as a free optimization.&lt;/p&gt;
&lt;p&gt;Adding a tool does not eliminate cost.&lt;br /&gt;
It relocates it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Caching shifts cost from IO to memory, CPU, serialization, and invalidation complexity.&lt;/li&gt;
&lt;li&gt;AI shifts cost from deterministic logic to probabilistic behavior, verification, and trust boundaries.&lt;/li&gt;
&lt;li&gt;Switching languages shifts cost from runtime to migration, tooling, and human expertise.&lt;/li&gt;
&lt;li&gt;Adding infrastructure shifts cost from simplicity to operations, failure modes, and long-term maintenance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you do not understand where the original cost lives, you will not notice where it moved. The system may look faster, smarter, or more modern, while becoming harder to reason about and easier to break.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Understanding is not optional&lt;/h2&gt;
&lt;p&gt;Real problem-solving requires understanding constraints, trade-offs, and failure modes. It requires knowing who pays the cost and when that cost surfaces.&lt;/p&gt;
&lt;p&gt;No tool can substitute for this. AI included.&lt;/p&gt;
&lt;p&gt;If AI truly understood systems, it would consistently identify root causes without human intervention. What we have instead is something more reflective than intelligent. It mirrors the depth of the thinking we put into it.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Closing thought&lt;/h2&gt;
&lt;p&gt;“Just use X” is rarely an answer.&lt;br /&gt;
More often, it is a signal.&lt;/p&gt;
&lt;p&gt;A signal that the problem has not been understood yet.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Open-source AI is not free, even on cloud GPUs</title><link>https://boraxpr.github.io/posts/freemodels</link><guid isPermaLink="true">https://boraxpr.github.io/posts/freemodels</guid><pubDate>Fri, 19 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lately I keep hearing the same pitch.&lt;/p&gt;
&lt;p&gt;Open-source AI models.&lt;br /&gt;
Run them yourself.&lt;br /&gt;
Even better, just use cloud GPUs.&lt;br /&gt;
No vendor lock-in. No per-token billing. Problem solved.&lt;/p&gt;
&lt;p&gt;It sounds clean. It sounds principled.&lt;br /&gt;
It also ignores how systems actually behave in production.&lt;/p&gt;
&lt;h2&gt;“Free weights” is a distraction&lt;/h2&gt;
&lt;p&gt;Yes, the model weights are free.&lt;br /&gt;
That part is true.&lt;/p&gt;
&lt;p&gt;What is not free is everything required to turn those weights into a reliable service.&lt;/p&gt;
&lt;p&gt;Inference is not a one-time cost. It is a continuous, operational expense. Once traffic exists, &lt;strong&gt;compute dominates the bill&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That reality does not change just because the GPU lives in the cloud.&lt;/p&gt;
&lt;h2&gt;Cloud GPUs do not change the economics&lt;/h2&gt;
&lt;p&gt;Using cloud GPUs sounds like a cheat code. No hardware to buy, no racks, no data center drama.&lt;/p&gt;
&lt;p&gt;In reality, cloud GPUs only change &lt;em&gt;how&lt;/em&gt; you pay, not &lt;em&gt;what&lt;/em&gt; you pay for.&lt;/p&gt;
&lt;p&gt;Inference workloads do not scale like stateless web servers. You cannot spin GPUs up and down freely without paying a penalty. Models take time to load, memory is sticky, and latency SLOs force you to keep capacity warm.&lt;/p&gt;
&lt;p&gt;So you provision for peaks, not averages.&lt;/p&gt;
&lt;p&gt;That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GPUs sit idle and still cost money.&lt;/li&gt;
&lt;li&gt;You pay retail pricing for specialized hardware.&lt;/li&gt;
&lt;li&gt;Redundancy multiplies the bill, not the reliability alone.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At small scale this looks acceptable.&lt;br /&gt;
At sustained traffic, the math stops being friendly.&lt;/p&gt;
&lt;p&gt;The cloud does not make this cheap.&lt;br /&gt;
It just delays when you notice the cost.&lt;/p&gt;
&lt;h2&gt;You are competing with hyperscalers on their own ground&lt;/h2&gt;
&lt;p&gt;Managed AI providers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Buy GPUs at prices you will never get.&lt;/li&gt;
&lt;li&gt;Run them close to constant utilization.&lt;/li&gt;
&lt;li&gt;Share infrastructure across thousands of customers.&lt;/li&gt;
&lt;li&gt;Optimize the full stack, from kernels to schedulers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you run open-source inference on cloud GPUs, you are paying retail to compete with companies built around wholesale economics.&lt;/p&gt;
&lt;p&gt;That gap never closes.&lt;/p&gt;
&lt;h2&gt;“We can optimize later” is wishful thinking&lt;/h2&gt;
&lt;p&gt;Performance is not an afterthought.&lt;br /&gt;
It is the product.&lt;/p&gt;
&lt;p&gt;Real inference optimization means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kernel-level tuning.&lt;/li&gt;
&lt;li&gt;Memory layout and KV cache strategy.&lt;/li&gt;
&lt;li&gt;Batching, queuing, and request shaping.&lt;/li&gt;
&lt;li&gt;Constant tradeoffs between latency and throughput.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Teams saying “we’ll optimize later” usually discover that optimization was the job they never staffed for.&lt;/p&gt;
&lt;p&gt;By then, production traffic has already locked in your worst costs.&lt;/p&gt;
&lt;h2&gt;Production is where the math becomes honest&lt;/h2&gt;
&lt;p&gt;POCs are cheap.&lt;br /&gt;
Production is not.&lt;/p&gt;
&lt;p&gt;As soon as users exist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Latency complaints arrive.&lt;/li&gt;
&lt;li&gt;Context lengths grow.&lt;/li&gt;
&lt;li&gt;Parallel requests increase.&lt;/li&gt;
&lt;li&gt;Reliability expectations harden.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One GPU becomes two.&lt;br /&gt;
Two become a pool.&lt;br /&gt;
The pool needs redundancy.&lt;br /&gt;
Now you are running GPU infrastructure, not just a model.&lt;/p&gt;
&lt;p&gt;At that point, the illusion of “free” is gone.&lt;/p&gt;
&lt;h2&gt;When this tradeoff actually makes sense&lt;/h2&gt;
&lt;p&gt;There &lt;em&gt;are&lt;/em&gt; valid reasons to run open-source AI yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Research and experimentation.&lt;/li&gt;
&lt;li&gt;Low, predictable internal workloads.&lt;/li&gt;
&lt;li&gt;Strict data locality or compliance needs.&lt;/li&gt;
&lt;li&gt;Existing infra and ML expertise.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice what is missing from that list, saving money by default.&lt;/p&gt;
&lt;h2&gt;The honest takeaway&lt;/h2&gt;
&lt;p&gt;Open-source AI is powerful.&lt;br /&gt;
Cloud GPUs are useful.&lt;/p&gt;
&lt;p&gt;But together they do not magically become cheap, simple, or risk-free.&lt;/p&gt;
&lt;p&gt;They are a conscious trade:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Less vendor lock-in.&lt;/li&gt;
&lt;li&gt;More operational responsibility.&lt;/li&gt;
&lt;li&gt;More hidden cost surfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That trade can be worth it.&lt;br /&gt;
Just do not pretend it is free.&lt;/p&gt;
&lt;p&gt;Reality always sends the invoice.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Excel Is Not Machine-Readable Data (And OCR Won’t Save You)</title><link>https://boraxpr.github.io/posts/ocrisfreewhydontweautomateyet</link><guid isPermaLink="true">https://boraxpr.github.io/posts/ocrisfreewhydontweautomateyet</guid><pubDate>Fri, 19 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OCR accuracy does not help if documents are full of process debt.&lt;/li&gt;
&lt;li&gt;Excel is a &lt;strong&gt;human-readable UI&lt;/strong&gt;, not a data contract.&lt;/li&gt;
&lt;li&gt;CSV and JSON are transport formats, not places where meaning lives.&lt;/li&gt;
&lt;li&gt;Without a database that enforces schema and semantics, automation will not scale.&lt;/li&gt;
&lt;li&gt;AI does not reduce cost. It merely relocates it into glue and exception handling.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;OCR Accuracy Is Not the Bottleneck&lt;/h2&gt;
&lt;p&gt;OCR news shows up constantly.&lt;br /&gt;
Higher accuracy. Lower cost. Better language support. Easier workflow integration.&lt;/p&gt;
&lt;p&gt;But the real question is not&lt;br /&gt;
&lt;strong&gt;Can you read the document?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The real question is&lt;br /&gt;
&lt;strong&gt;What can you do with the output next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Most enterprise documents were never designed to be machine-readable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rows exist for reasons nobody remembers.&lt;/li&gt;
&lt;li&gt;Addresses are split across pages due to legacy system limits.&lt;/li&gt;
&lt;li&gt;The same field means different things in different departments.&lt;/li&gt;
&lt;li&gt;Codes like &lt;code&gt;01&lt;/code&gt; or &lt;code&gt;AZ1202&lt;/code&gt; require asking someone or opening another document.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OCR solves only one step:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pixel → text&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Automation requires something very different:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;text → meaning → action&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And this is where most systems break down.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The Real Enemy Is Tribal Knowledge&lt;/h2&gt;
&lt;p&gt;You can have 120 percent OCR accuracy.&lt;br /&gt;
It still does not matter if meaning lives in people.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“What does code 01 mean? Ask someone.”&lt;/li&gt;
&lt;li&gt;“This code needs to be looked up in another Excel file.”&lt;/li&gt;
&lt;li&gt;“These two fields are actually one value.”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At that point, human-in-the-loop is not optional.&lt;br /&gt;
It is a hard requirement.&lt;/p&gt;
&lt;p&gt;AI cannot fix this, because the problem is not intelligence.&lt;br /&gt;
The problem is &lt;strong&gt;undefined semantics&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Guessing is non-deterministic.&lt;br /&gt;
Non-deterministic systems cannot be audited.&lt;br /&gt;
Unauditable systems do not survive production.&lt;/p&gt;
&lt;p&gt;This is not technical debt.&lt;br /&gt;
It is &lt;strong&gt;organizational debt&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Excel Is Human-Readable First&lt;/h2&gt;
&lt;p&gt;Excel is readable by machines.&lt;br /&gt;
But it was never designed to be machine-readable.&lt;/p&gt;
&lt;p&gt;Excel is a UI for humans.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;merged cells&lt;/li&gt;
&lt;li&gt;color-coded meaning&lt;/li&gt;
&lt;li&gt;floating headers&lt;/li&gt;
&lt;li&gt;notes mixed with data&lt;/li&gt;
&lt;li&gt;formulas that depend on context&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Machines can parse Excel files.&lt;br /&gt;
Machines cannot reliably infer meaning from them.&lt;/p&gt;
&lt;p&gt;Excel works well when humans are part of the loop.&lt;br /&gt;
It fails as the foundation of automation.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;CSV and JSON Are Not Storage&lt;/h2&gt;
&lt;p&gt;A common misconception is that converting Excel to CSV or JSON makes data machine-readable.&lt;/p&gt;
&lt;p&gt;It does not.&lt;/p&gt;
&lt;p&gt;CSV and JSON are &lt;strong&gt;transport formats&lt;/strong&gt;.&lt;br /&gt;
They are not sources of truth.&lt;/p&gt;
&lt;p&gt;No serious system stores long-term meaning in CSV or JSON files.&lt;/p&gt;
&lt;p&gt;What you actually need is a &lt;strong&gt;database&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A database enforces things files never will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;schema&lt;/li&gt;
&lt;li&gt;constraints&lt;/li&gt;
&lt;li&gt;referential integrity&lt;/li&gt;
&lt;li&gt;versioned structure&lt;/li&gt;
&lt;li&gt;deterministic queries&lt;/li&gt;
&lt;li&gt;auditability&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without these guarantees, you are not storing data.&lt;br /&gt;
You are storing ambiguity.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Cost Did Not Disappear. It Moved.&lt;/h2&gt;
&lt;p&gt;Before OCR and AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;people type&lt;/li&gt;
&lt;li&gt;people check&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After OCR and AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;people interpret intent&lt;/li&gt;
&lt;li&gt;people maintain mappings&lt;/li&gt;
&lt;li&gt;people fix exceptions&lt;/li&gt;
&lt;li&gt;people maintain the bridge between OCR, AI, and the database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The cost does not go away.&lt;br /&gt;
It gets redistributed, often into more expensive roles.&lt;/p&gt;
&lt;p&gt;Over time, that bridge layer becomes the next generation of process debt.&lt;br /&gt;
“Do not touch it. It will break.”&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Excel as a Source of Truth Is Just Vibe Coding for Data&lt;/h2&gt;
&lt;p&gt;Using Excel as a source of machine truth is equivalent to letting a vibe coder do a database engineer’s job.&lt;/p&gt;
&lt;p&gt;A database engineer’s responsibility is to make meaning explicit and enforced.&lt;br /&gt;
Schema, constraints, references, invariants, migrations, ownership.&lt;br /&gt;
The system is allowed to say no.&lt;/p&gt;
&lt;p&gt;Excel does the opposite.&lt;/p&gt;
&lt;p&gt;Excel is permissive by design.&lt;br /&gt;
Anything goes. Any shape. Any workaround.&lt;br /&gt;
Validation is optional. Semantics are implicit. Errors are silent.&lt;/p&gt;
&lt;p&gt;That is exactly how vibe-coded systems behave.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rules live in someone’s head.&lt;/li&gt;
&lt;li&gt;Structure emerges accidentally.&lt;/li&gt;
&lt;li&gt;Edge cases are handled “later.”&lt;/li&gt;
&lt;li&gt;Everything works until scale or automation shows up.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When Excel becomes the source of truth, the failure modes are the same:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Schema drift with no visibility.&lt;/li&gt;
&lt;li&gt;Business rules encoded in layouts, colors, or side documents.&lt;/li&gt;
&lt;li&gt;Integrity enforced socially instead of technically.&lt;/li&gt;
&lt;li&gt;Automation that breaks the moment a new person touches the file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It feels productive at first.&lt;br /&gt;
You move fast. Nothing blocks you.&lt;/p&gt;
&lt;p&gt;Until auditability, reliability, or automation becomes a requirement.&lt;br /&gt;
Then everything collapses at once.&lt;/p&gt;
&lt;p&gt;The core problem is simple:&lt;br /&gt;
you replaced enforced contracts with vibes.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;If You Want Automation, Redesign First&lt;/h2&gt;
&lt;p&gt;If an organization is serious about automation, the hard work comes first:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;eliminate tribal knowledge&lt;/li&gt;
&lt;li&gt;define a canonical schema&lt;/li&gt;
&lt;li&gt;create a single source of truth&lt;/li&gt;
&lt;li&gt;enforce validation&lt;/li&gt;
&lt;li&gt;reject ambiguous input&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is process redesign, not tooling.&lt;/p&gt;
&lt;p&gt;Deploying AI before doing this is cosmetic engineering.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;OCR is not failing.&lt;br /&gt;
AI is not failing.&lt;/p&gt;
&lt;p&gt;Organizations fail when they refuse to formalize their own knowledge&lt;br /&gt;
and expect intelligence to emerge from ambiguity.&lt;/p&gt;
&lt;p&gt;As long as meaning lives in people instead of systems,&lt;br /&gt;
people will always be pulled back into the loop.&lt;/p&gt;
&lt;p&gt;No model, no matter how advanced, can change that.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Some Models Are Flashy. Some Models Are Forever.</title><link>https://boraxpr.github.io/posts/themodel</link><guid isPermaLink="true">https://boraxpr.github.io/posts/themodel</guid><pubDate>Sun, 21 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;image-5.png&quot; alt=&quot;alt text&quot; /&gt;
Every few months, the industry discovers &lt;strong&gt;the next model&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This time it’s&lt;br /&gt;
&lt;em&gt;Gemini 3 Pro Ultra Whatever™.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Next time it’s &lt;em&gt;3.5&lt;/em&gt;, and suddenly we’re back to&lt;br /&gt;
&lt;strong&gt;“human race extinction is imminent.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Same movie. New trailer.&lt;/p&gt;
&lt;p&gt;Benchmarks go up.&lt;br /&gt;
Slides get cleaner.&lt;br /&gt;
Threads declare &lt;em&gt;“this changes everything”&lt;/em&gt; before the weights even finish uploading.&lt;/p&gt;
&lt;p&gt;And just like that, the timeline resets.&lt;br /&gt;
New year. New model. Same prophecy.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The part everyone forgets&lt;/h2&gt;
&lt;p&gt;What the industry conveniently forgets&lt;br /&gt;
or never learned in the first place&lt;br /&gt;
is that none of this runs in a vacuum.&lt;/p&gt;
&lt;p&gt;Most “vibe coders” have never heard of the &lt;strong&gt;OSI Model&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Not because it’s outdated.&lt;br /&gt;
Because it’s boring.&lt;/p&gt;
&lt;p&gt;No hype cycle.&lt;br /&gt;
No launch event.&lt;br /&gt;
No extinction countdown.&lt;/p&gt;
&lt;p&gt;Yet this unsexy, decades-old abstraction&lt;br /&gt;
is still quietly holding the entire internet together.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;The longest-running model in tech&lt;/h2&gt;
&lt;p&gt;Packets still move.&lt;br /&gt;
Failures still cascade at Layer 1–3.&lt;br /&gt;
Latency still ruins your “AI-native” demo.&lt;br /&gt;
And debugging still begins with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Is the network actually up?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The OSI Model doesn’t get rebranded.&lt;br /&gt;
There is no OSI 3.5.&lt;br /&gt;
No OSI Pro Max.&lt;/p&gt;
&lt;p&gt;It doesn’t promise to replace humans.&lt;br /&gt;
It just ensures your miracle model can talk to anything at all.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;OSI isn’t alone&lt;/h2&gt;
&lt;p&gt;The OSI Model isn’t special because it’s old.&lt;br /&gt;
It’s special because it never needed rebranding.&lt;/p&gt;
&lt;p&gt;And it’s not the only one.&lt;/p&gt;
&lt;p&gt;Modern systems quietly run on models most hype-driven engineers never name:
consistency tradeoffs, failure domains, queueing behavior, latency budgets,
organizational incentives.&lt;/p&gt;
&lt;p&gt;They don’t trend.
They don’t ship with release notes.
They don’t care how smart the next model is.&lt;/p&gt;
&lt;p&gt;They just describe reality.&lt;/p&gt;
&lt;p&gt;You don’t replace these models.
You inherit them.&lt;/p&gt;
&lt;p&gt;Yet everything depends on them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CAP Theorem&lt;/strong&gt; – pick two, live with the third&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ACID&lt;/strong&gt; – because data loss isn’t a “temporary inconvenience”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amdahl’s Law&lt;/strong&gt; – your AI won’t fix the slow part you ignored&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latency budgets&lt;/strong&gt; – physics still clocks your ambition&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queueing theory&lt;/strong&gt; – why your “agent swarm” collapses under load&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Failure domains&lt;/strong&gt; – why one smart model can still take everything down&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Intelligence doesn’t bypass physics&lt;/h2&gt;
&lt;p&gt;Every year, we announce a new intelligence revolution.&lt;br /&gt;
Every year, we forget the same fundamentals.&lt;/p&gt;
&lt;p&gt;Models get smarter.&lt;br /&gt;
Reality stays stubborn.&lt;/p&gt;
&lt;p&gt;Your system still:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;times out&lt;/li&gt;
&lt;li&gt;drops packets&lt;/li&gt;
&lt;li&gt;fails under load&lt;/li&gt;
&lt;li&gt;breaks at Layer 8&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Some models are flashy. Some models are forever.&lt;/h2&gt;
&lt;p&gt;The future may be intelligent.&lt;br /&gt;
It may reason.&lt;br /&gt;
It may generate code faster than you can read it.&lt;/p&gt;
&lt;p&gt;But it will still run on networks.&lt;br /&gt;
It will still fail in mundane ways.&lt;br /&gt;
And it will still depend on models that never trend on social media.&lt;/p&gt;
&lt;p&gt;Some models chase headlines.&lt;br /&gt;
Some models just keep the world running.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Technical Avoidance and Its Impact on Thai Tech</title><link>https://boraxpr.github.io/posts/thaitechquality</link><guid isPermaLink="true">https://boraxpr.github.io/posts/thaitechquality</guid><pubDate>Fri, 26 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;People like to preach as if Thai tech is on par with Silicon Valley.&lt;/p&gt;
&lt;p&gt;You hear it all the time.&lt;/p&gt;
&lt;p&gt;Silicon Valley says software engineering is cooling down,&lt;br /&gt;
so people here assume the same thing will happen to Thailand.&lt;/p&gt;
&lt;p&gt;No. It will not.&lt;/p&gt;
&lt;p&gt;Our tech industry is built on completely different assumptions, incentives, and realities.&lt;br /&gt;
At the most basic level, it is a different ecosystem.&lt;/p&gt;
&lt;h2&gt;Capability vs density&lt;/h2&gt;
&lt;p&gt;The US does not win because every engineer there is a genius.&lt;br /&gt;
They win because they have &lt;strong&gt;a higher density of people who take technical depth seriously&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In stronger programs, students are pushed into real engineering work early. Many of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build or modify operating systems&lt;/li&gt;
&lt;li&gt;Write parts of compilers or runtimes&lt;/li&gt;
&lt;li&gt;Treat systems programming as normal, not exotic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not everyone does this, and plenty still coast.&lt;br /&gt;
But there is a critical mass that pulls everything forward.&lt;/p&gt;
&lt;p&gt;In Thailand:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Year 1: Hello World&lt;/li&gt;
&lt;li&gt;Year 2: Hello World, now object-oriented&lt;/li&gt;
&lt;li&gt;Year 3: Hello World, now with a database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is not an insult. That is curriculum design.&lt;/p&gt;
&lt;p&gt;This is not because the US is magical.&lt;br /&gt;
They built environments, incentives, and expectations that force more people to go deeper.&lt;/p&gt;
&lt;p&gt;You do not close a gap by denying it exists.&lt;/p&gt;
&lt;h2&gt;The root problem is not talent, it is avoidance&lt;/h2&gt;
&lt;p&gt;When I was in college, the majority of people I knew &lt;strong&gt;hated coding.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not struggled with it.&lt;br /&gt;
Not found it hard but interesting.&lt;br /&gt;
They outright hated it.&lt;/p&gt;
&lt;p&gt;They would do anything except code.&lt;/p&gt;
&lt;p&gt;Why were they there?&lt;br /&gt;
Almost always, “my parents told me to study this.”&lt;/p&gt;
&lt;p&gt;That is not unusual here.&lt;br /&gt;
But the downstream effects are brutal.&lt;/p&gt;
&lt;h3&gt;Do anything except the hard part&lt;/h3&gt;
&lt;p&gt;This mindset repeats everywhere:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do anything except coding&lt;/li&gt;
&lt;li&gt;Do anything except math&lt;/li&gt;
&lt;li&gt;Do anything except systems&lt;/li&gt;
&lt;li&gt;Do anything except responsibility&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not because the subject is impossible.&lt;br /&gt;
Because changing direction is costly, and avoiding the discomfort feels safer.&lt;/p&gt;
&lt;p&gt;So people stay in careers they dislike and optimize for escape routes.&lt;/p&gt;
&lt;p&gt;Slides.&lt;br /&gt;
Presentations.&lt;br /&gt;
Buzzwords.&lt;br /&gt;
Process.&lt;/p&gt;
&lt;p&gt;I still remember forming a group for a term project.&lt;br /&gt;
One friend said, without hesitation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I’ll do anything except coding.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That sentence explains a lot.&lt;/p&gt;
&lt;h2&gt;Fast forward: our tech job landscape&lt;/h2&gt;
&lt;p&gt;Years later, the same avoidance patterns show up again, this time institutionalized as career tracks.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tester&lt;/li&gt;
&lt;li&gt;Business analyst&lt;/li&gt;
&lt;li&gt;Project manager&lt;/li&gt;
&lt;li&gt;System analyst&lt;/li&gt;
&lt;li&gt;AI engineer&lt;/li&gt;
&lt;li&gt;Architect&lt;/li&gt;
&lt;li&gt;And more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These roles are legitimate when they stay connected to engineering reality.&lt;/p&gt;
&lt;p&gt;The problem starts when they become &lt;strong&gt;escape hatches from responsibility&lt;/strong&gt;, while still controlling direction.&lt;/p&gt;
&lt;p&gt;People end up directing implementation without having to carry the cost of executing it.&lt;br /&gt;
And once that structure exists, it reinforces itself.&lt;/p&gt;
&lt;p&gt;Within those structures, cargo-cult narratives thrive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Developers will be replaced by AI”&lt;/li&gt;
&lt;li&gt;“Just use AI”&lt;/li&gt;
&lt;li&gt;“Coding won’t matter anymore”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are not San Francisco, and pretending otherwise only keeps us stuck.&lt;/p&gt;
&lt;h2&gt;Compare this with the US reality&lt;/h2&gt;
&lt;p&gt;In healthier tech ecosystems, many managerial roles are held by people who:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have shipped real systems&lt;/li&gt;
&lt;li&gt;Understand where things usually break&lt;/li&gt;
&lt;li&gt;Can drop into the weeds when necessary&lt;/li&gt;
&lt;li&gt;Give implementation-level guidance instead of slogans&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not all of them. There is plenty of fluff there too,&lt;br /&gt;
but there is a larger share of people who have actually done the work.&lt;/p&gt;
&lt;p&gt;It is not perfect. They have cargo cult behavior too.&lt;br /&gt;
The difference is that more people recognize it when it shows up.&lt;/p&gt;
&lt;p&gt;The idea exists in Thailand, but it is rarely discussed openly, and almost never named.&lt;/p&gt;
&lt;p&gt;In Thailand, not always, but often, direction stops at “go do [buzzword].”&lt;/p&gt;
&lt;p&gt;Meanwhile:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Testers frequently write code.&lt;/li&gt;
&lt;li&gt;Architects are usually engineers who have survived multiple failures.&lt;/li&gt;
&lt;li&gt;AI engineers tend to be strong developers who later moved into a specialized domain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I came across a comment from an AI engineer that summed it up:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I wish I weren’t an AI engineer.&lt;br /&gt;
The pay isn’t much better than dev,&lt;br /&gt;
but the job is still dev plus ops plus unclear requirements.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That line says a lot.&lt;/p&gt;
&lt;p&gt;AI engineering there is not a shortcut.&lt;br /&gt;
It is extra responsibility stacked on people who already know how to build.&lt;/p&gt;
&lt;h2&gt;Thailand’s AI illusion&lt;/h2&gt;
&lt;p&gt;In Thailand, too many “AI engineer” roles are built around optics instead of engineering.&lt;/p&gt;
&lt;p&gt;The selection criteria often look like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Polished English&lt;/li&gt;
&lt;li&gt;Beautiful slides&lt;/li&gt;
&lt;li&gt;Fluency in buzzwords&lt;/li&gt;
&lt;li&gt;Comfort presenting to executives&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But when it comes to fundamentals, things fall apart.&lt;/p&gt;
&lt;p&gt;Roadmaps get written that the authors cannot execute.&lt;br /&gt;
Milestones are “validated” by LLM answers they do not know how to evaluate.&lt;/p&gt;
&lt;p&gt;That is not innovation.&lt;br /&gt;
That is theater.&lt;/p&gt;
&lt;p&gt;Leadership often ends up rewarding the theater, because it is easier to measure slide decks and demos than real technical resilience.&lt;/p&gt;
&lt;h2&gt;Reality check&lt;/h2&gt;
&lt;p&gt;Even if AI wiped out a lot of coding jobs in Silicon Valley tomorrow,&lt;br /&gt;
it would not wipe them out in Thailand anytime soon.&lt;/p&gt;
&lt;p&gt;Because we still do not have enough people who can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Debug deeply&lt;/li&gt;
&lt;li&gt;Trace problems across systems&lt;/li&gt;
&lt;li&gt;Own outcomes end to end&lt;/li&gt;
&lt;li&gt;Take responsibility when things break&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI does not replace absence.&lt;br /&gt;
AI amplifies capability that already exists.&lt;/p&gt;
&lt;p&gt;If you cannot reason about systems, AI only helps you produce wrong answers faster.&lt;/p&gt;
&lt;h2&gt;If we want to move forward&lt;/h2&gt;
&lt;p&gt;We need to stop lying to ourselves.&lt;/p&gt;
&lt;p&gt;This is not about nationalism.&lt;br /&gt;
It is not about pride.&lt;/p&gt;
&lt;p&gt;It is about admitting that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our education system rarely rewards real technical depth&lt;/li&gt;
&lt;li&gt;Our workplaces often reward appearances over mastery&lt;/li&gt;
&lt;li&gt;Our leadership pipelines filter for presentation more than competence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Until those incentives change, no amount of “Thai talent is world-class” posts will make it true.&lt;/p&gt;
&lt;p&gt;You do not close a gap by denying it.&lt;br /&gt;
You close it by telling the truth first, then building differently.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>AI and the Illusion of Easy Work</title><link>https://boraxpr.github.io/posts/dunningkrugerllm</link><guid isPermaLink="true">https://boraxpr.github.io/posts/dunningkrugerllm</guid><pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;2026-01-09-21-49-37.png&quot; alt=&quot;dunningkruger&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;image from : https://www.icopilots.com/strategyzer-and-the-dunning-kruger-effect/&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&apos;s a pattern I keep seeing lately, especially with AI and LLMs.&lt;/p&gt;
&lt;p&gt;When people don&apos;t understand a field, they think it&apos;s easy.&lt;br /&gt;
When they understand it a little, they think AI lets them replace it.&lt;br /&gt;
When they actually understand it deeply, they stop making bold claims.&lt;/p&gt;
&lt;p&gt;That&apos;s not opinion. That&apos;s Dunning–Kruger.&lt;/p&gt;
&lt;h3&gt;The illusion of &quot;easy work&quot;&lt;/h3&gt;
&lt;p&gt;Non-coders say coding is easy now. AI writes code. Why hire developers?&lt;/p&gt;
&lt;p&gt;Some developers say business is easy now. AI writes marketing copy.&lt;br /&gt;
&quot;I&apos;ll just go solopreneur and bag the cash myself.&quot;&lt;/p&gt;
&lt;p&gt;Others say we don’t need mathematicians, lawyers, security engineers, designers, or analysts anymore. AI already knows more than humans. Who needs verification when confidence feels good?&lt;/p&gt;
&lt;p&gt;This logic always comes from the same place: not knowing what the real work actually is.&lt;/p&gt;
&lt;p&gt;People confuse &lt;strong&gt;output&lt;/strong&gt; with &lt;strong&gt;expertise&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;What expertise really looks like&lt;/h3&gt;
&lt;p&gt;Expertise is not typing faster.&lt;br /&gt;
It&apos;s not producing artifacts.&lt;br /&gt;
It&apos;s not knowing syntax, formulas, or buzzwords.&lt;/p&gt;
&lt;p&gt;Expertise is knowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;where things fail&lt;/li&gt;
&lt;li&gt;which assumptions are dangerous&lt;/li&gt;
&lt;li&gt;which edge cases matter&lt;/li&gt;
&lt;li&gt;what cannot be trusted&lt;/li&gt;
&lt;li&gt;how context changes decisions&lt;/li&gt;
&lt;li&gt;when a &quot;correct&quot; answer is still wrong&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are the parts AI struggles with the most. Not because the model is bad, but because these things live outside clean inputs and clean rules.&lt;/p&gt;
&lt;h3&gt;LLMs make ignorance louder, not smarter&lt;/h3&gt;
&lt;p&gt;LLMs are extremely good at sounding right.&lt;br /&gt;
They are extremely bad at telling you when they are wrong.&lt;/p&gt;
&lt;p&gt;If you don&apos;t know a domain well enough, you will not spot hallucinations. You won&apos;t even know what to verify. You&apos;ll accept confident nonsense because it aligns with what you already believe.&lt;/p&gt;
&lt;p&gt;That&apos;s why people who lack depth are often the most confident about replacement. They cannot see the gaps, so they assume there are none.&lt;/p&gt;
&lt;h3&gt;Why &quot;AI will replace X&quot; is usually a tell&lt;/h3&gt;
&lt;p&gt;When someone says AI will replace a profession, what they are really saying is this:&lt;/p&gt;
&lt;p&gt;&quot;I don&apos;t understand what that profession actually does.&quot;&lt;/p&gt;
&lt;p&gt;Security is not just writing secure code.&lt;br /&gt;
Design is not just drawing interfaces.&lt;br /&gt;
Business is not just writing pitches.&lt;br /&gt;
Math is not just producing answers.&lt;/p&gt;
&lt;p&gt;If any of those were true, those fields would have collapsed long before AI showed up.&lt;/p&gt;
&lt;h3&gt;The uncomfortable conclusion&lt;/h3&gt;
&lt;p&gt;AI does not flatten the skill curve.&lt;br /&gt;
It steepens it.&lt;/p&gt;
&lt;p&gt;It removes shallow work and exposes shallow thinking.&lt;br /&gt;
It rewards people who understand systems, constraints, and failure modes.&lt;br /&gt;
It punishes people who mistake surface-level competence for mastery.&lt;/p&gt;
&lt;p&gt;Experience doesn&apos;t make you louder.&lt;br /&gt;
It makes you more careful.&lt;/p&gt;
&lt;p&gt;If something looks easy, the honest move is not confidence.&lt;br /&gt;
It&apos;s suspicion.&lt;/p&gt;
&lt;p&gt;Because the moment everything feels obvious is usually the moment you&apos;ve stopped seeing what matters.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>TanStack is optional. Somehow it got sold as mandatory.</title><link>https://boraxpr.github.io/posts/reactcap</link><guid isPermaLink="true">https://boraxpr.github.io/posts/reactcap</guid><pubDate>Sat, 10 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;TanStack is optional.&lt;/p&gt;
&lt;p&gt;That’s the entire point that keeps getting lost.&lt;/p&gt;
&lt;p&gt;Somewhere along the way, it stopped being presented as a tool with tradeoffs and started being sold as a &lt;em&gt;must use&lt;/em&gt; for React developers.&lt;/p&gt;
&lt;p&gt;Not as “use this when it fits.”&lt;br /&gt;
Not as “here’s what it solves.”&lt;br /&gt;
But as a baseline.&lt;/p&gt;
&lt;p&gt;Once that narrative sets in, people stop thinking.&lt;/p&gt;
&lt;p&gt;Newer developers assume it’s required.&lt;br /&gt;
They reach for it by default.&lt;br /&gt;
And when you ask &lt;em&gt;why&lt;/em&gt;, the answers are vague.&lt;/p&gt;
&lt;p&gt;“Better performance.”&lt;br /&gt;
“Industry standard.”&lt;br /&gt;
“Everyone uses it.”&lt;br /&gt;
“It handles caching.”&lt;/p&gt;
&lt;p&gt;None of those explain why &lt;em&gt;this app&lt;/em&gt; needs it.&lt;/p&gt;
&lt;p&gt;It starts to feel less like engineering and more like belief.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The truth is simpler.&lt;/p&gt;
&lt;p&gt;TanStack solves a &lt;strong&gt;specific class of problems&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;shared server state&lt;/li&gt;
&lt;li&gt;read-heavy data&lt;/li&gt;
&lt;li&gt;background revalidation&lt;/li&gt;
&lt;li&gt;convenience around caching&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s it.&lt;/p&gt;
&lt;p&gt;It does not make data more correct.&lt;br /&gt;
It does not eliminate race conditions.&lt;br /&gt;
It does not replace thinking about async behavior.&lt;/p&gt;
&lt;p&gt;It just gives you tools.&lt;/p&gt;
&lt;p&gt;Useful ones.&lt;br /&gt;
Optional ones.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The moment you introduce a client-side cache, you introduce time as a concern.&lt;/p&gt;
&lt;p&gt;Multiple requests in flight.&lt;br /&gt;
Out-of-order responses.&lt;br /&gt;
Background refetch.&lt;br /&gt;
Mutations racing reads.&lt;br /&gt;
Optimistic updates guessing the future.&lt;/p&gt;
&lt;p&gt;Now you’re not just fetching data.&lt;br /&gt;
You’re reasoning about ordering, invalidation, and overwrite windows.&lt;/p&gt;
&lt;p&gt;That complexity is real, even if the abstraction hides it.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;What gets glossed over is that &lt;strong&gt;most apps don’t need this&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Fetching on demand works.&lt;/p&gt;
&lt;p&gt;Component mounts, fetch.&lt;br /&gt;
User acts, refetch.&lt;br /&gt;
Server stays authoritative.&lt;/p&gt;
&lt;p&gt;It’s slower.&lt;br /&gt;
It shows loading states.&lt;br /&gt;
And it’s correct.&lt;/p&gt;
&lt;p&gt;I’d rather show a spinner than lie.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;There &lt;em&gt;are&lt;/em&gt; places where TanStack fits well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;app configuration&lt;/li&gt;
&lt;li&gt;feature flags&lt;/li&gt;
&lt;li&gt;read-heavy, low-mutation reference data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice the pattern.&lt;/p&gt;
&lt;p&gt;Global meaning.&lt;br /&gt;
Rare writes.&lt;br /&gt;
Tolerance for brief staleness.&lt;/p&gt;
&lt;p&gt;That’s not most CRUD.&lt;/p&gt;
&lt;p&gt;Auth isn’t one of them either.&lt;br /&gt;
Auth should be validated by the server on every page or navigation. It’s security-critical and intolerant to staleness.&lt;/p&gt;
&lt;p&gt;If calling an auth endpoint on every page is a problem, that’s a backend issue, not a reason to cache it on the client.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The problem isn’t TanStack.&lt;/p&gt;
&lt;p&gt;The problem is how it’s talked about.&lt;/p&gt;
&lt;p&gt;When a tool is oversold as mandatory, people stop evaluating it.&lt;br /&gt;
They stop understanding it.&lt;br /&gt;
They stop questioning whether it fits.&lt;/p&gt;
&lt;p&gt;At that point, it’s no longer a tool.&lt;br /&gt;
It’s doctrine.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;So no, I don’t use TanStack by default.&lt;/p&gt;
&lt;p&gt;Not because it’s bad.&lt;br /&gt;
Not because it’s useless.&lt;/p&gt;
&lt;p&gt;Because it’s optional.&lt;br /&gt;
And treating optional tools as mandatory is how complexity sneaks in unnoticed.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Speed VS Velocity - What is Productivity</title><link>https://boraxpr.github.io/posts/speedvsvelocity</link><guid isPermaLink="true">https://boraxpr.github.io/posts/speedvsvelocity</guid><pubDate>Sun, 15 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Most organizations obsess over two metrics: Productivity and Capability. But we’ve stripped these words of their meaning.&lt;/p&gt;
&lt;p&gt;In the modern corporate machine, these terms have been oversimplified into dangerous caricatures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Productivity is reduced to: &quot;Are all your time slots filled?&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Capability is reduced to: &quot;Do you know more today than you did last year?&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is why this logic is failing the people who actually build the systems.&lt;/p&gt;
&lt;h3&gt;Productivity : The Utilization Myth&lt;/h3&gt;
&lt;p&gt;If you squeeze your people hard enough, you can achieve 100% time utilization. Everyone is &quot;busy.&quot; Everyone has a full calendar.&lt;/p&gt;
&lt;p&gt;But the missing variable is Value.&lt;/p&gt;
&lt;p&gt;When management talks about productivity, they assume the tasks assigned are beneficial to the organization. But what if they aren&apos;t? What if most tasks exist solely to appear &quot;busy&quot; or to satisfy a hollow KPI?&lt;/p&gt;
&lt;p&gt;When &quot;Speed&quot; becomes the excuse for rushing out &quot;trash work,&quot; you aren&apos;t being productive. You are just creating a high-speed assembly line for features no one uses and systems no one can maintain.&lt;/p&gt;
&lt;h3&gt;Speed is Not Velocity&lt;/h3&gt;
&lt;p&gt;We often hear that &quot;the business can’t wait,&quot; so we need more speed of execution.&lt;/p&gt;
&lt;p&gt;But Speed is a scalar; it’s just how fast you’re moving. Velocity is a vector; it’s speed with a specific direction. If your organization demands speed without velocity, you aren&apos;t building a product; you’re building a junkyard. You might cross the finish line fast, but you’ll leave behind a mess of technical debt that someone else—usually your most capable engineers—will have to clean up later. Moving fast in the wrong direction provides zero benefit to the organization.&lt;/p&gt;
&lt;h3&gt;Capability : The Infinite Horizon&lt;/h3&gt;
&lt;p&gt;&quot;Know more than yesterday.&quot; It sounds noble, but in a dysfunctional system, it becomes a burden. At what point is it enough?&lt;/p&gt;
&lt;p&gt;When the organization prioritizes &quot;speed&quot; (trash work) over &quot;velocity&quot; (meaningful direction), the most capable people are punished. They are the ones expected to learn every new tool, fix every legacy disaster, and teach every new hire-only to watch the cycle repeat.&lt;/p&gt;
&lt;p&gt;Capability without a meaningful goal isn&apos;t growth. It&apos;s just a faster way to burn out.&lt;/p&gt;
&lt;h3&gt;The Bottom Line&lt;/h3&gt;
&lt;p&gt;If you are measuring productivity by how many hours your engineers are &quot;busy,&quot; you’ve already lost the plot. Stop asking for speed. Start defining the velocity.&lt;/p&gt;
&lt;p&gt;Otherwise, you’re just paying people to build a pile of junk faster.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Can&apos;t Unsee It: The KPI Work Factory</title><link>https://boraxpr.github.io/posts/kpiwork</link><guid isPermaLink="true">https://boraxpr.github.io/posts/kpiwork</guid><pubDate>Mon, 23 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I used to wonder why engineering teams are constantly bombarded with work. Why the backlog never shrinks, and why every day feels like a sprint.&lt;/p&gt;
&lt;p&gt;After years in the industry, delivering projects and witnessing dozens of others, the realization finally hit me. And once you see it, you can’t unsee it.&lt;/p&gt;
&lt;h2&gt;Much of the industry&apos;s work is just &quot;KPI Work.&quot;&lt;/h2&gt;
&lt;p&gt;It’s work designed to satisfy a metric, not a user. It’s work created to justify a budget, not to solve a problem. These projects are launched, celebrated in slide decks, and then quietly left to rot because they have absolutely zero impact on anything that actually matters.&lt;/p&gt;
&lt;p&gt;Instead of building a product, teams often end up building a paper trail of &quot;achievement.&quot;&lt;/p&gt;
&lt;p&gt;Companies burn their best engineers on these hollow tasks just so someone can check a box at the end of the quarter. Architecture, stability, and sanity are sacrificed to maintain the illusion of progress.&lt;/p&gt;
&lt;p&gt;It’s an exhausting cycle of moving at high speed toward a destination that doesn&apos;t exist. If &quot;Productivity&quot; means being 100% utilized on projects that provide zero value, then we aren&apos;t being productive. We’re just being busy while the ship stays in the same place.&lt;/p&gt;
&lt;p&gt;The question shouldn&apos;t be &quot;How can we work faster?&quot;
The question must be &quot;Why are we doing this at all?&quot;&lt;/p&gt;
&lt;h2&gt;The Missing Feedback Loop&lt;/h2&gt;
&lt;p&gt;The most terrifying part of a KPI Work Factory isn’t the useless projects—it’s the total absence of a feedback loop.&lt;/p&gt;
&lt;p&gt;When success is defined by &apos;finishing&apos; rather than &apos;solving,&apos; we lose our North Star. Without feedback from real-world performance metrics, we are flying blind. How can teams know where to improve if they don&apos;t even know where they are? How can they iterate when they are already being forced to sprint toward the next hollow goal?&lt;/p&gt;
&lt;p&gt;The irony is that in a culture of corporate &apos;politeness,&apos; you’ll rarely hear the truth. If you have a good connection or if you&apos;re just a decent colleague, no one will ever look you in the eye and say, &quot;This system doesn&apos;t actually solve our problem, and we never use it.&quot;&lt;/p&gt;
&lt;p&gt;They’ll just smile, thank you for the hard work, and let the project rot in silence.&lt;/p&gt;
&lt;p&gt;In the absence of brutal, data-driven feedback, we aren&apos;t just flying blind; we’re operating on a false premise.&lt;/p&gt;
&lt;h2&gt;Breaking the Cycle&lt;/h2&gt;
&lt;p&gt;To escape the KPI Work Factory, we have to start demanding to see the impact.&lt;/p&gt;
&lt;p&gt;As engineers and product builders, we need to ask harder questions before the sprint even begins. What is the baseline metric we are trying to move? How will we measure adoption? What does failure look like for this feature?&lt;/p&gt;
&lt;p&gt;If the answers aren&apos;t clear, the project isn&apos;t ready. We have to shift the culture from celebrating output to celebrating outcomes. Until we tie our engineering efforts to actual user value rather than internal scorecards, the factory will just keep humming along.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>AI Fatigue and peak of non-tech expectation</title><link>https://boraxpr.github.io/posts/aifatigue</link><guid isPermaLink="true">https://boraxpr.github.io/posts/aifatigue</guid><pubDate>Sat, 07 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I think I’ve hit AI fatigue.&lt;/p&gt;
&lt;p&gt;Not because I don’t use it. I use it every day. Constantly. It’s part of how I debug, design, and ship systems. I was following this space long before mass enterprise adoption, before every executive suddenly had an “AI strategy.”&lt;/p&gt;
&lt;p&gt;What burns me out is the noise. The endless wave of headlines and demos with the same tired promise: &lt;em&gt;“AI will replace us in 6–12 months.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This narrative should’ve died already. If AI is going to replace me, then replace me. Don’t warn me. Don’t hype it. Don’t count down. If the replacement is real, just do it. Otherwise, stop the clock.&lt;/p&gt;
&lt;h3&gt;The Gap Between Demo and Reality&lt;/h3&gt;
&lt;p&gt;Instead of replacement, we get an endless sequence of tools: Copilot, Claude Computer Use, Cursor, Claude Code, and an army of &quot;agents.&quot; Each is framed as the moment humans become optional.&lt;/p&gt;
&lt;p&gt;And yet, I use them every day, and I find mistakes every single day. Not rare edge cases—daily, systemic errors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Flawed Assumptions&lt;/strong&gt;: Logic that breaks the moment it hits a real-world constraint.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hallucinated Syntax&lt;/strong&gt;: Code that looks elegant but relies on non-existent libraries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confidently Incorrect Logic&lt;/strong&gt;: Solutions that pass a superficial glance but fail under load.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Wiring Probability into Determinism&lt;/h3&gt;
&lt;p&gt;The current push is to connect these systems directly to actions—letting them run commands, modify infrastructure, and operate production environments with the assumption that it will “just work.”&lt;/p&gt;
&lt;p&gt;It won’t. At its core, an LLM is a &lt;strong&gt;probabilistic system&lt;/strong&gt;. It predicts; it does not &quot;know.&quot; It does not verify unless forced. It does not carry responsibility.&lt;/p&gt;
&lt;p&gt;We spent decades engineering &lt;strong&gt;deterministic systems&lt;/strong&gt; because predictability and reliability matter. Now, we’re wiring probabilistic engines into deterministic infrastructure and hoping for the best.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hope is not an engineering strategy.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;The Human Bottleneck: Judgment&lt;/h3&gt;
&lt;p&gt;AI is the most powerful force-multiplier I’ve ever used. It removes friction and lets one person do the work of many. But &lt;strong&gt;acceleration is not replacement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The bottleneck in software engineering was never typing speed; it was &lt;strong&gt;judgment&lt;/strong&gt;. It’s the ability to know something is wrong even when it looks correct. AI can generate at light speed, but it cannot care if it’s right.&lt;/p&gt;
&lt;p&gt;So I’m done with the countdowns. If replacement arrives, it won’t be through a press release or a flashy demo. It will arrive quietly, when the results finally speak louder than the hype.&lt;/p&gt;
&lt;p&gt;Until then, I’ll keep using it. And I’ll definitely keep checking its work.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Scaling Multi-Tenant Runtimes: Why Isolation is Mandatory at 500+ DAU</title><link>https://boraxpr.github.io/posts/cloudprovidertrap</link><guid isPermaLink="true">https://boraxpr.github.io/posts/cloudprovidertrap</guid><pubDate>Sat, 07 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Managing an internal AI platform (OpenWebUI/LiteLLM) at a &lt;strong&gt;500+ DAU scale&lt;/strong&gt; is a constant lesson in the high cost of &quot;Optics.&quot; When working with innovative teams that demand the latest Gemini models the morning they drop, high velocity is expected. But following the hype is easy—noticing the wall before you hit it is the real engineering challenge.&lt;/p&gt;
&lt;h2&gt;The Prototype Fallacy&lt;/h2&gt;
&lt;p&gt;A centralized terminal feature is a perfect example. A prototype for 1-2 users in a sandbox is trivial. Releasing it to 500+ users without strict &lt;strong&gt;Kernel-level Isolation&lt;/strong&gt; is an invitation to disaster.&lt;/p&gt;
&lt;p&gt;If you don&apos;t have isolation, you aren&apos;t running a platform; you&apos;re running a ticking time bomb:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The &quot;RAG&quot; Data-Plane Failure&lt;/strong&gt;: Choosing a model for &quot;superior accuracy&quot; is a common trap. In the real world, a single RAG response can hit &lt;strong&gt;300MB+ of JSON&lt;/strong&gt;. Without resource limits, this causes a pod to die on arrival due to OOM (Out of Memory) before the data can even be processed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The &quot;Vibe Coder&quot; Failure&lt;/strong&gt;: It only takes one &quot;vibe coder&quot; running a single &lt;strong&gt;naive&lt;/strong&gt;, unoptimized script to leak memory or fork-bomb the shared runtime. Without isolation, that one volatile process causes total failure for every other user on the terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency Collisions&lt;/strong&gt;: User A’s Python 3.10 requirement breaking User B’s 3.12 environment. Relying on &quot;pre-prompting&quot; an agent to handle isolation is a naive safeguard; in a probabilistic system, there is &lt;strong&gt;zero guarantee&lt;/strong&gt; of compliance. One hallucinated &lt;code&gt;pip install&lt;/code&gt; or a manual override is enough to corrupt the environment for the entire pool.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security &amp;amp; Integrity&lt;/strong&gt;: The risk of environment variables leaking secrets between users, or a &quot;watch the world burn&quot; moment where a user executes &lt;code&gt;sudo rm -rf /&lt;/code&gt;—taking the entire platform offline and triggering an emergency on-call recovery.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Total Cost of Ownership vs. &quot;Optics&quot;&lt;/h2&gt;
&lt;p&gt;The only way to do this right is &lt;strong&gt;Dynamic Provisioning&lt;/strong&gt;—effectively becoming an internal Cloud Provider. Each user needs a dedicated, isolated slice: 1-2 cores, 4GB RAM, and 50GB of persistent storage.&lt;/p&gt;
&lt;p&gt;Building it is the easy part; surviving the &lt;strong&gt;Day 2 operations&lt;/strong&gt;—patching, scaling, and handling the stateful storage of 500 isolated environments—is where the real cost hides.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The hard truth&lt;/strong&gt;: The Total Cost of Ownership (TCO) for a production-grade system is vastly different from a prototype. You quickly find yourself building an internal replication of a clearly under-resourced and under-business-value &lt;strong&gt;Azure Cloud Shell&lt;/strong&gt;. If the business value doesn&apos;t justify the massive resource overhead and the technical stakeholders aren&apos;t heard, you aren&apos;t building a platform—you&apos;re building an empire waiting to fall.&lt;/p&gt;
&lt;p&gt;In platform engineering, the goal isn&apos;t just to make it work; it&apos;s to make it survive the scale.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>I&apos;m not going to be a part of the Dead Internet: I&apos;m back to 100% hand-written posts.</title><link>https://boraxpr.github.io/posts/deadinternet</link><guid isPermaLink="true">https://boraxpr.github.io/posts/deadinternet</guid><pubDate>Sun, 15 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;./handwritten.png&quot; alt=&quot;handwritten&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The Dead internet is a phenomenon which majority of content online—previously crafted by humans—is now being automated by LLMS. In 2026, we&apos;re seeing &quot;samey&quot; contents all over social media. It all sounds the same; It all gives the same calls-to-action, key takeaways and advice.&lt;/p&gt;
&lt;p&gt;Jokingly, I sometimes even guess which model a writer used. Gemini, ChatGPT, Claude each have their own signature writing styles (I can feel it because I&apos;ve been using all of them).&lt;/p&gt;
&lt;p&gt;It&apos;s not just images and videos; I highly suspected the majority of content creators are using AI to generate their writings. Even with friends, normies are starting to sound identical, which, in my book, defeats the purpose of creating content.&lt;/p&gt;
&lt;p&gt;Personally, I&apos;ve been using AI to refine and edit my posts, but I&apos;ve reached a point where I have a hard time expressing my authentic thoughts. Because I use AI so regularly, I&apos;m officially quitting the habit of using it to &quot;make my writing better.&quot; I might still ask for insights or basic grammar fixes, but no more automated writing. It defeats the purpose of the act itself.&lt;/p&gt;
&lt;p&gt;Would it still be &quot;me&quot; writing if 80% of it is AI?. For a long time, I convinced myself the answer was yes. But lately, it’s become difficult to tell which thoughts are actually mine.&lt;/p&gt;
&lt;p&gt;From now on, my posts will be 100% hand-written.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item><item><title>Low Maturity Software Culture: They want order-takers, not systems-thinkers</title><link>https://boraxpr.github.io/posts/lowmaturitysoftwareculture</link><guid isPermaLink="true">https://boraxpr.github.io/posts/lowmaturitysoftwareculture</guid><pubDate>Tue, 24 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the Thai market, I find it truly challenging to find the right place for me. As a systems-thinker, I evaluate every order and reject the ones that don&apos;t make sense. I focus on doing what is right for long-term maintainability.&lt;/p&gt;
&lt;p&gt;However, what I’ve found in Low Maturity Software Culture is that most stakeholders don’t want systems-thinkers. Even though we actively prevent &quot;the shit hitting the fan&quot; so they never have to feel the pain, egos and corporate culture often get in the way. They ignore us, prioritizing optics and relationships over working systems.&lt;/p&gt;
&lt;p&gt;Once the system is shipped and the KPI checkbox is green, the Business moves on. The app is in production. But when the cracks inevitably show, the failure is blamed on the implementers, not the flawed logic that forced it.&lt;/p&gt;
&lt;p&gt;They want order takers. not me, never will be able to fit in to that role. And when shit happens according to their order being followed to the letter (otherwise they would label you as difficult) they blame you.&lt;/p&gt;
&lt;p&gt;Weird of all things, most if not all world top software such as Google, Facebook, Apple and I&apos;d argue many products that are able to hit mass adoption are this scalable because they listen to the doers.
recently, i&apos;ve been into a HBO MAX Series named &quot;Sillicon Valley&quot;, I feel like technological advancement, usable and working longterm products can not and will not magically appear because a group of dev listen and execute based on business stakeholder word by words, character by characters.&lt;/p&gt;
&lt;p&gt;The main character in Silicon Valley had two offers to choose from. He built a world-class, efficient compression and search algorithm. He was offered 10M USD to instantly buy his algorithm, but he chose to accept 200,000 and support for the business to grow his own app instead. That&apos;s what I&apos;m talking about.&lt;/p&gt;
&lt;p&gt;As far as thai tech market is heading, I only see disappointment, demo driven development. what these people do is replaced their own software once in a while with an external vendor (who doesn&apos;t even own the platform if they aren&apos;t buying MA support).&lt;/p&gt;
&lt;p&gt;It is architecturally difficult to make a great software product in Thailand.&lt;/p&gt;
&lt;p&gt;3-5 years ago, we were talking &quot;hey, kids should go to computer science&quot;. But when the kids went to computer science and came out. You don&apos;t listen to them but instead listen to MBA people.&lt;/p&gt;
&lt;p&gt;One of the tolls of working in this sort of environment and culture is that your engineering skills will vanish within years. You won&apos;t know what is logically or architecturally right anymore because you&apos;re forced to do what &quot;someone important&quot; wants to happen.&lt;/p&gt;
&lt;p&gt;Maybe it&apos;s just the culture of tech as supporting, not business value center but as a cost center.&lt;br /&gt;
Maybe one day it would be better.&lt;/p&gt;
</content:encoded><author>Boraxpr</author></item></channel></rss>