<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[web complex]]></title><description><![CDATA[The complexity of the web is what makes it attractive.]]></description><link>https://blog.yasaichi.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 19:20:15 GMT</lastBuildDate><atom:link href="https://blog.yasaichi.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Choose Languages for Leverage, Not Loyalty]]></title><description><![CDATA[For most of modern software history, choosing a programming language meant navigating limitations.Ecosystems, tooling quality, runtime guarantees, and team experience forced trade-offs. Language decisions were as much about constraints as they were a...]]></description><link>https://blog.yasaichi.com/choose-languages-for-leverage-not-loyalty</link><guid isPermaLink="true">https://blog.yasaichi.com/choose-languages-for-leverage-not-loyalty</guid><category><![CDATA[AI]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Mon, 01 Dec 2025 19:44:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/HMBugh3HZ0M/upload/22c6cfa6c115629d56c843fdb886c5c9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For most of modern software history, choosing a programming language meant navigating limitations.<br />Ecosystems, tooling quality, runtime guarantees, and team experience forced trade-offs. Language decisions were as much about constraints as they were about strategy.</p>
<h2 id="heading-ai-changed-the-equation">AI Changed the Equation</h2>
<p>AI is changing that dynamic.</p>
<p><a target="_blank" href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/">The latest GitHub Octoverse report</a> highlights an emerging pattern: AI accelerates languages that offer structure, strong ecosystems, and predictable abstractions. TypeScript continues to rise because AI agents can reason about typed code. Python remains dominant because it owns the tooling ecosystem for data, research, and AI. The patterns are driven not by sentiment, but by leverage loops.</p>
<p>What sits underneath this trend is simple: AI models are better at languages they’ve seen vastly more examples of, and languages whose structure reduces ambiguity. If a model has seen a trillion examples of TypeScript and only thousands of Haskell, it will inevitably be better at generating and refactoring TypeScript.</p>
<p>Typed languages also help AI reason about intent — structure acts as a guide rail. A related analysis, <a target="_blank" href="https://github.blog/news-insights/octoverse/typescript-python-and-the-ai-feedback-loop-changing-software-development/">“TypeScript, Python, and the AI feedback loop changing software development”</a>, frames this trend clearly: typed and well-structured languages benefit most in the era of AI assistance and generation.</p>
<p>This shift surfaces an important mindset:</p>
<blockquote>
<p>In the AI era, languages should be chosen for leverage — not loyalty.</p>
</blockquote>
<p>Yet many engineering cultures still operate from loyalty-based reasoning:</p>
<ul>
<li><p>"Everything should be TypeScript because we’re a JS company."</p>
</li>
<li><p>"Everything should be Go because it’s production-ready."</p>
</li>
<li><p>"Everything should be Python because AI happens there."</p>
</li>
</ul>
<p>Uniformity feels elegant. But uniformity does not automatically scale.</p>
<p>If we instead ask:</p>
<blockquote>
<p>“Where does each language provide the most leverage for its layer of the system?”</p>
</blockquote>
<p>a more realistic and future-proof architecture emerges. Because once the frame shifts from preference to leverage, the criteria for choosing a language changes too.</p>
<h2 id="heading-a-leverage-aligned-stack">A Leverage-Aligned Stack</h2>
<h3 id="heading-frontend"><strong>Frontend</strong></h3>
<p>TypeScript is the default. Its ecosystem, tooling, and AI support make it the natural place for user-facing development.</p>
<h3 id="heading-backend-application-logic"><strong>Backend Application Logic</strong></h3>
<p>TypeScript performs well here, especially when paired with contract-first API design. AI support accelerates iteration, prototyping, and refactoring — and most business logic benefits more from speed and clarity than from micro-optimized runtime characteristics.</p>
<h3 id="heading-high-performance-or-long-lived-services"><strong>High-Performance or Long-Lived Services</strong></h3>
<p>Some workloads such as schedulers, workers, streaming processors, and high-throughput edge compute, require predictable memory characteristics and runtime stability. Here, Go becomes a natural choice. Not because TypeScript is incapable, but because operational predictability becomes the dominant force.</p>
<h3 id="heading-infrastructure-and-platform-software"><strong>Infrastructure and Platform Software</strong></h3>
<p>Infrastructure tooling lives in a different ecosystem. Terraform uses HCL — not because it's expressive, but because it enforces consistency. And when things need to be extended or written as providers, the ecosystem gravitates toward Go, because the tooling around Kubernetes, operators, Envoy, and most modern cloud-native foundations are written in Go.</p>
<p>This layer is optimized not for flexibility, but for durability and predictability.</p>
<h3 id="heading-ai-ml-data-systems"><strong>AI / ML / Data Systems</strong></h3>
<p>Python remains uniquely positioned. Its ecosystem, libraries, research velocity, and AI-native frameworks give it continued leverage in domains where experimentation and iteration matter. It isn’t the fastest language, but speed of idea flow outweighs execution cost in this domain, and that reality won’t change soon.</p>
<h2 id="heading-the-new-decision-model">The New Decision Model</h2>
<p>AI lowers the friction of learning a new language. The hard part is no longer syntax; it’s architecture. If boundaries are explicit with schemas, contracts, protocols, queues, and messaging patterns, different languages can coexist cleanly.</p>
<p>So the question is no longer:</p>
<blockquote>
<p>“Which language should we standardize everything on?”</p>
</blockquote>
<p>but rather:</p>
<blockquote>
<p>“Where does this language give us the highest return on effort — for humans, for systems, and for AI?”</p>
</blockquote>
<p>Once framed that way, the emerging pattern — at least for now — becomes clearer:</p>
<ul>
<li><p>TypeScript where iteration speed and architecture flexibility matter.</p>
</li>
<li><p>Go where operational stability and runtime behaviour matter.</p>
</li>
<li><p>Python where AI, ML, and analytical workflows live.</p>
</li>
</ul>
<p>Not everything needs Go.<br />Not everything needs TypeScript.<br />Not everything needs Python.</p>
<p>But everything <em>SHOULD</em> have a reason.</p>
<hr />
<blockquote>
<p>The takeaway isn’t about switching stacks. It’s about <strong>optimizing for leverage, not loyalty.</strong></p>
<p>The languages and tools that survive the next decade won’t be the ones developers love most—they’ll be the ones that give developers <em>and</em> machines the most shared advantage.</p>
<p><a target="_blank" href="https://github.blog/news-insights/octoverse/typescript-python-and-the-ai-feedback-loop-changing-software-development/">“TypeScript, Python, and the AI feedback loop changing software development”</a></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[When You See Abstract Structures, Design Becomes Easier]]></title><description><![CDATA[While developing an e-commerce system, I once designed a model called DeliveryDateConstraint to represent delivery restrictions decided by sellers. At first, it looked simple enough: each product had its own shipping rule.But later I realised that cu...]]></description><link>https://blog.yasaichi.com/when-you-see-abstract-structures-design-becomes-easier</link><guid isPermaLink="true">https://blog.yasaichi.com/when-you-see-abstract-structures-design-becomes-easier</guid><category><![CDATA[modeling]]></category><category><![CDATA[data structure and algorithms ]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Sat, 08 Nov 2025 17:10:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/TyZhkVuK658/upload/f98330b79a3641261c2a93c07e3fe1e3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While developing an e-commerce system, I once designed a model called <code>DeliveryDateConstraint</code> to represent delivery restrictions decided by sellers. At first, it looked simple enough: each product had its own shipping rule.<br />But later I realised that customers and delivery schedules also limit when a product can actually arrive. All those conditions could be described as “available dates.” That discovery led me to extract a value object named <code>AvailableDateSet</code>. At that moment I felt that abstraction is not invention — it is discovery.</p>
<h2 id="heading-seeing-structure-enables-generalisation">Seeing Structure Enables Generalisation</h2>
<p>Originally, the model handled only the seller’s side.<br />Then I noticed that “available delivery dates” were nothing more than <strong>an intersection of date sets</strong>.<br />From this point of view, a seller, a customer, and delivery timing all share the same structure: each provides a set of dates, and their intersection defines what is possible.</p>
<pre><code class="lang-ruby">earliest_delivery_date = (
  customer.preferred_delivery_dates &amp;
  product.available_delivery_dates &amp;
  shipping_schedule.available_delivery_dates
).min
</code></pre>
<p>Generalisation happened not because of creative imagination, but because I recognised the underlying structure — a <strong>set</strong>.</p>
<p>Knowing common data structures such as <em>sets</em>, <em>ranges</em>, <em>trees</em>, and <em>graphs</em> gives us a language to describe problems more precisely.<br />Once we have that vocabulary, we can see through the surface of business rules and find simpler, reusable forms beneath them.</p>
<h2 id="heading-standard-libraries-as-dictionaries-of-structures">Standard Libraries as Dictionaries of Structures</h2>
<p>Language standard libraries are, in a sense, museums of reusable structures.<br />In Ruby, for instance, <code>Enumerable</code> abstracts the pattern of iteration; <code>Range</code> represents an interval that can apply to numbers or dates; and <code>Set</code> formalises an unordered collection of unique elements.<br />Each of these abstractions was born from many developers solving similar problems and then recognising a pattern that could be generalised.</p>
<p>Reading a standard library is like reading a dictionary of abstract data structures.<br />You can find how earlier engineers captured everyday patterns—iteration, ordering, containment—and turned them into composable building blocks.<br />Those structures often provide the missing words we need to express our own domain models more clearly.</p>
<h2 id="heading-knowing-structures-lets-you-delay-design-decisions">Knowing Structures Lets You Delay Design Decisions</h2>
<p>When I introduced <code>AvailableDateSet</code>, I didn’t need to handle every type of restriction at once.<br />Because I knew the concept of a <em>set</em>, I understood that other constraints—customer or delivery-related—could later be merged through intersection.<br />Knowing these underlying forms lets you <strong>delay generalisation</strong> until the right moment.<br />You can start simple, stay consistent, and expand when reality demands it.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Abstraction in software design is not a leap of imagination but a process of discovering existing structures.<br />Those structures—sets, ranges, trees, graphs—are already part of the common language of computation.<br />They live quietly inside every standard library, waiting to be noticed and reused.</p>
<p>When you struggle with a complex domain, try looking for a familiar shape within it.<br />The right abstract structure may already exist, and once you see it, your design will naturally become lighter and more flexible.</p>
]]></content:encoded></item><item><title><![CDATA[Presentation (JA): TSKaigi 2025]]></title><description><![CDATA[Deck


https://decks.yasaichi.com/20250524/pragmatic-functional-programming-in-typescript
Abstract
Functional programming concepts such as pure functions, immutability, and monads are increasingly familiar to TypeScript developers, yet many struggle ...]]></description><link>https://blog.yasaichi.com/presentation-ja-tskaigi-2025</link><guid isPermaLink="true">https://blog.yasaichi.com/presentation-ja-tskaigi-2025</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[#Domain-Driven-Design]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Sun, 25 May 2025 23:00:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-deck">Deck</h2>
<iframe src="https://decks.yasaichi.com/20250524/pragmatic-functional-programming-in-typescript"></iframe>

<p><a target="_blank" href="https://decks.yasaichi.com/20250524/pragmatic-functional-programming-in-typescript">https://decks.yasaichi.com/20250524/pragmatic-functional-programming-in-typescript</a></p>
<h2 id="heading-abstract">Abstract</h2>
<p>Functional programming concepts such as pure functions, immutability, and monads are increasingly familiar to TypeScript developers, yet many struggle to apply them effectively in production systems. The gap is not in theory, but in understanding how these ideas translate into maintainable, real-world code.</p>
<p>This session reframes the five principles proposed by Dmitrii Kovanikov—<em>Parse, Don’t Validate</em>; <em>Make Illegal States Unrepresentable</em>; <em>Errors as Values</em>; <em>Functional Core, Imperative Shell</em>; and <em>Smart Constructors</em>—through the lens of Design by Contract, focusing on preconditions, postconditions, and invariants as a practical mental model. Using TypeScript examples, I will demonstrate how these principles improve correctness, extensibility, and resilience in evolving systems.</p>
<p>I will also present a case study from EARTHBRAIN’s API gateway development effort, illustrating how these principles integrate with tactical DDD and layered architecture. Attendees will gain actionable patterns that apply not only to backend services, but also to complex, stateful frontend applications.</p>
<p>By the end of the session, participants will have a clear methodology for applying functional programming pragmatically—bridging conceptual understanding and production-grade implementation.</p>
]]></content:encoded></item><item><title><![CDATA[Handling Known and Unknown Unknowns with Testing and Observability]]></title><description><![CDATA[In modern software development, we often face three types of risks:

Known knowns: issues we are aware of and understand.

Known unknowns: issues we know exist but lack full understanding.

Unknown unknowns: issues we neither know exist nor understan...]]></description><link>https://blog.yasaichi.com/handling-known-and-unknown-unknowns-with-testing-and-observability</link><guid isPermaLink="true">https://blog.yasaichi.com/handling-known-and-unknown-unknowns-with-testing-and-observability</guid><category><![CDATA[Rumsfeld matrix]]></category><category><![CDATA[Testing]]></category><category><![CDATA[property-based testing]]></category><category><![CDATA[logging]]></category><category><![CDATA[observability]]></category><category><![CDATA[SRE]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Mon, 28 Apr 2025 10:07:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FFYSD72ktiU/upload/d750f142fb178d85c7de51ff40fdca86.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In modern software development, we often face three types of risks:</p>
<ol>
<li><p><em>Known knowns</em>: issues we are aware of and understand.</p>
</li>
<li><p><em>Known unknowns</em>: issues we know exist but lack full understanding.</p>
</li>
<li><p><em>Unknown unknowns</em>: issues we neither know exist nor understand.</p>
</li>
</ol>
<p>This article explores testing techniques for known knowns and known unknowns, and shows how logging and observability help us convert unknown unknowns into known risks. We’ll also see how Site Reliability Engineering (SRE) practices fit into this picture.</p>
<h2 id="heading-1-understanding-known-knowns-and-known-unknowns">1. Understanding Known Knowns and Known Unknowns</h2>
<ul>
<li><p><em>Known knowns</em> are clear requirements or behaviors already captured by tests.</p>
</li>
<li><p><em>Known unknowns</em> are areas we suspect might fail, but we don’t know the exact nature of the failure.</p>
</li>
</ul>
<p>For example, we may know that a user-input parser must handle Unicode strings (<em>known unknown</em>), but we lack precise examples of problematic inputs.</p>
<h2 id="heading-2-testing-techniques-for-known-knowns-and-known-unknowns">2. Testing Techniques for Known Knowns and Known Unknowns</h2>
<h3 id="heading-21-unit-and-integration-tests">2.1 Unit and Integration Tests</h3>
<ul>
<li><p><em>Unit tests</em> verify specific functions or methods with fixed inputs and outputs.</p>
</li>
<li><p><em>Integration tests</em> check the interaction between multiple components.</p>
</li>
</ul>
<p>These approaches are excellent for covering <em>known knowns</em>, because they focus on explicit, pre-defined cases.</p>
<h3 id="heading-22-property-based-testing">2.2 Property-Based Testing</h3>
<p>Property-based testing flips the script: instead of writing individual test cases, we define <em>properties</em> that should always hold. For instance:</p>
<ul>
<li><p>A sorting function should always return a list of the same length, with elements in non-decreasing order.</p>
</li>
<li><p>A JSON serializer followed by a deserializer should yield the original object.</p>
</li>
</ul>
<p>By generating thousands of random inputs, property-based testing helps uncover <em>edge cases</em>, turning some <em>known unknowns</em> into <em>known knowns</em>.</p>
<h2 id="heading-3-from-unknown-unknowns-to-known-knowns-logging-and-observability">3. From Unknown Unknowns to Known Knowns: Logging and Observability</h2>
<p>While testing covers many issues, some problems only appear in production under real-world conditions. These are the <em>unknown unknowns</em>. To discover them, we rely on:</p>
<h3 id="heading-31-structured-logging">3.1 Structured Logging</h3>
<ul>
<li><p><em>Contextual logs</em> record key variables and execution paths.</p>
</li>
<li><p><em>Log levels</em> (INFO, WARN, ERROR) help prioritise messages.</p>
</li>
</ul>
<p>Good logging makes unexpected behaviour visible, turning <em>unknown unknowns</em> into <em>known unknowns</em> that we can investigate.</p>
<h3 id="heading-32-metrics-and-monitoring">3.2 Metrics and Monitoring</h3>
<ul>
<li><p><em>Counters</em> track event occurrences (e.g., request rates, error counts).</p>
</li>
<li><p><em>Gauges</em> measure values over time (e.g., memory usage).</p>
</li>
<li><p><em>Alerts</em> notify teams when metrics cross thresholds.</p>
</li>
</ul>
<p>By observing metric spikes or trends, we identify anomalies that testing missed, shifting issues from <em>unknown</em> to <em>known</em>.</p>
<h3 id="heading-33-tracing-and-distributed-context">3.3 Tracing and Distributed Context</h3>
<ul>
<li><p><em>Distributed tracing</em> maps request flows across services, showing latency and errors per segment.</p>
</li>
<li><p><em>Trace IDs</em> link logs and metrics to individual user requests.</p>
</li>
</ul>
<p>Tracing reveals complex failure modes in microservice architectures, converting <em>unknowns</em> into testable scenarios.</p>
<h3 id="heading-34-cultivating-an-observability-culture">3.4 Cultivating an Observability Culture</h3>
<ul>
<li><p><em>Post-mortems</em> document incidents, root causes, and preventive actions.</p>
</li>
<li><p><em>Blameless analysis</em> encourages team collaboration and continuous improvement.</p>
</li>
</ul>
<p>Observability is not just tools—it’s a mindset that embraces uncertainty and learns from real-world failures.</p>
<h2 id="heading-4-sre-and-the-convergence-of-practices">4. SRE and the Convergence of Practices</h2>
<p>Site Reliability Engineering combines testing, logging, and observability:</p>
<ul>
<li><p>SRE teams define <em>service level objectives (SLOs)</em> to guide alerts and dashboards.</p>
</li>
<li><p><em>Error budgets</em> balance innovation against reliability, using real-time data.</p>
</li>
<li><p>Collaboration between dev and ops ensures that <em>unknown unknowns</em> are surfaced early and learned from.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By applying:</p>
<ul>
<li><p><em>Unit/integration tests</em> for <em>known knowns</em>,</p>
</li>
<li><p><em>Property-based testing</em> for <em>known unknowns</em>, and</p>
</li>
<li><p><em>Logging + observability</em> for <em>unknown unknowns</em>,</p>
</li>
</ul>
<p>We build resilient systems that adapt and improve. Embracing these practices bridges the gap between what we expect and what happens, turning every <em>unknown</em> into an opportunity for learning.</p>
<blockquote>
<p>“There are unknown unknowns; the ones we don’t know we don’t know.”<br />– <em>Donald Rumsfeld</em>, Wikipedia: <a target="_blank" href="https://en.wikipedia.org/wiki/There_are_unknown_unknowns">Unknown unknowns</a></p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Improving Primary Key Performance: Alternatives to UUID v4]]></title><description><![CDATA[In many applications, a primary key must be unique and hard to guess. Developers often choose UUID v4 for these benefits. However, there are trade-offs in performance.
Pros and Cons of Using UUID v4 as a Primary Key
UUID v4 gives global uniqueness an...]]></description><link>https://blog.yasaichi.com/improving-primary-key-performance-alternatives-to-uuid-v4</link><guid isPermaLink="true">https://blog.yasaichi.com/improving-primary-key-performance-alternatives-to-uuid-v4</guid><category><![CDATA[uuid]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Sun, 16 Mar 2025 23:00:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GNyjCePVRs8/upload/673bf4f2ee0e852568d9cb5ee6f79423.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In many applications, a primary key must be unique and hard to guess. Developers often choose UUID v4 for these benefits. However, there are trade-offs in performance.</p>
<h2 id="heading-pros-and-cons-of-using-uuid-v4-as-a-primary-key">Pros and Cons of Using UUID v4 as a Primary Key</h2>
<p>UUID v4 gives global uniqueness and improves security because its random nature makes it hard to predict record order. Clients can even generate IDs without extra database calls. However, this randomness harms performance. The non-sequential order leads to poor index locality, increased disk I/O, and frequent page splits, especially during writes. In addition, the 128-bit size uses more storage than regular integers.</p>
<h2 id="heading-why-mysql-suffers-more-index-and-data-structure-differences">Why MySQL Suffers More: Index and Data Structure Differences</h2>
<p>MySQL’s InnoDB engine uses a clustered B+Tree where table data is stored along with the primary key. With sequential keys, new records are added to the end of the tree, keeping data on the same pages and improving cache hit rates. UUID v4, being random, scatters inserts over many pages. This causes frequent page splits and increases disk I/O, which degrades performance. PostgreSQL, by contrast, stores data separately from the index, so it suffers less from this issue.</p>
<h2 id="heading-a-better-alternative-binary-storage-and-ordered-id-schemes">A Better Alternative: Binary Storage and Ordered ID Schemes</h2>
<p>One solution is to store IDs in binary form (<code>BINARY(16)</code>) rather than as strings, which improves storage efficiency and reduces comparison overhead. Even better, using an ordered ID—such as a time-ordered UUID (v6 or v7) or alternatives like Snowflake IDs or ULIDs—can improve performance. Both Snowflake IDs and ULIDs include a timestamp that makes new records nearly sequential. Note that NanoIDs, by default, are generated randomly and do not embed a time component (see <a target="_blank" href="https://planetscale.com/blog/why-we-chose-nanoids-for-planetscales-api">Why we chose NanoIDs for PlanetScale’s API</a> for more details).</p>
<h2 id="heading-4-conclusion">4. Conclusion</h2>
<p>While UUID v4 offers many advantages in security and distributed systems, its randomness can degrade performance, especially in MySQL’s clustered index environment. Storing IDs in binary and adopting an ordered ID scheme—whether a time-ordered UUID (v6/v7) or an alternative like Snowflake IDs or ULIDs—can achieve near-sequential order, improving index efficiency and overall database performance in both MySQL and PostgreSQL.</p>
]]></content:encoded></item><item><title><![CDATA[LLM Instructions as Part of Web Frameworks]]></title><description><![CDATA[The rise of artificial intelligence in software development brings many benefits, but also some challenges. One problem is that AI models sometimes slow down the use of new and better technologies. This happens because AI tools are trained with data ...]]></description><link>https://blog.yasaichi.com/llm-instructions-as-part-of-web-frameworks</link><guid isPermaLink="true">https://blog.yasaichi.com/llm-instructions-as-part-of-web-frameworks</guid><category><![CDATA[llm]]></category><category><![CDATA[AI]]></category><category><![CDATA[web framework]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[encore]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Sun, 09 Mar 2025 15:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1xE5QnNXJH0/upload/8b36d8f45bdafc5e61d08893609e25e5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The rise of artificial intelligence in software development brings many benefits, but also some challenges. One problem is that AI models sometimes slow down the use of new and better technologies. This happens because AI tools are trained with data that stops at a certain point, and they follow system prompts that affect their responses.</p>
<h2 id="heading-how-ai-influences-technology-choices">How AI Influences Technology Choices</h2>
<p>Many AI tools are built with system prompts that encourage the use of popular technologies such as React or Tailwind. Because these tools appear frequently in the training data, they are often suggested even when newer technologies might be better. This bias is explained in the essay <a target="_blank" href="https://vale.rocks/posts/ai-is-stifling-tech-adoption">AI is Stifling Tech Adoption</a>.</p>
<p>Given this bias, it is important to explore solutions that address these limitations.</p>
<h2 id="heading-a-possible-solution-llm-instructions-in-web-frameworks">A Possible Solution: LLM Instructions in Web Frameworks</h2>
<p>One way to solve this problem is to update the AI tools with new guidelines. By "LLM instructions" we mean a set of updated guidelines that tell the Large Language Model (LLM) how to behave using the most up-to-date information available. <a target="_blank" href="https://encore.dev/">Encore.ts</a> is a framework that includes these guidelines as part of its system<a target="_blank" href="https://github.com/encoredev/encore/blob/a506b633c840ce0abbde3a9a2bb554b95a23e49c/ts_llm_instructions.txt">^1</a>. The content can be updated as the framework evolves, so that the LLM is always working with the latest data. This approach can help encourage the use of new and promising technologies that might otherwise be ignored.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>AI models help many developers, but they can also slow down the adoption of new technologies because they rely on old training data and fixed system prompts. Using updated LLM instructions provided by web frameworks—such as the approach taken by <a target="_blank" href="https://encore.dev/">Encore.ts</a>—offers a possible solution. With up-to-date guidelines, developers can receive more accurate support from LLMs, which can lead to increased adoption of new technologies.</p>
]]></content:encoded></item><item><title><![CDATA[Deno in Production: A Real-World Experience in 2024]]></title><description><![CDATA[In the ever-evolving landscape of web development, choosing the right technology can be challenging. As I work on a project re-vamping an API gateway, I've recently explored Deno as our JavaScript runtime, and I'd like to share my insights from our p...]]></description><link>https://blog.yasaichi.com/deno-in-production-2024</link><guid isPermaLink="true">https://blog.yasaichi.com/deno-in-production-2024</guid><category><![CDATA[Deno]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[nestjs]]></category><category><![CDATA[vitest]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Tue, 03 Dec 2024 15:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/fwULOOEWHto/upload/b988d5ac4b9105ae99498d0bb3fe1f83.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the ever-evolving landscape of web development, choosing the right technology can be challenging. As I work on a project re-vamping an API gateway, I've recently explored Deno as our JavaScript runtime, and I'd like to share my insights from our production journey.</p>
<h2 id="heading-compatibility-and-performance">Compatibility and Performance</h2>
<p>Deno v2 was a significant milestone that resolved many Node.js compatibility issues. While some minor challenges remain, the runtime has proven surprisingly robust. The application using NestJS runs smoothly, and I've particularly appreciated the ability to compile binaries that dramatically reduce our Docker container sizes.</p>
<h2 id="heading-development-experience-and-tooling">Development Experience and Tooling</h2>
<p>The developer experience with Deno has been mostly positive. Instead of relying on traditional tools like ESLint or Prettier, I've found Deno's built-in linter and formatter more than adequate. However, I encountered a notable challenge with dependency management: Renovate, a popular automated dependency update tool, doesn't seem to support Deno's <code>deno.lock</code> file fully. As a workaround, I've been using pnpm to manage our dependencies effectively.</p>
<h2 id="heading-testing-and-monitoring-limitations">Testing and Monitoring Limitations</h2>
<p>Testing has been an area with room for improvement. While Vitest works, the lack of VS Code plugin support and incomplete V8 coverage implementation<a target="_blank" href="https://github.com/denoland/deno/issues/23882#issuecomment-2494138782">^1</a> can be frustrating. I've transitioned to using <code>@std/testing</code>, an official testing tool provided by the Deno team. Similarly, OpenTelemetry support remains partial, though official improvements are in progress<a target="_blank" href="https://docs.deno.com/api/deno/~/Deno.telemetry">^2</a>.</p>
<h2 id="heading-a-pragmatic-approach">A Pragmatic Approach</h2>
<p>My strategy involves maintaining flexibility. By avoiding Deno-specific APIs and keeping a <code>package.json</code>, I ensure I can seamlessly transition back to Node.js if needed. This risk mitigation approach has been crucial.</p>
<h2 id="heading-looking-forward">Looking Forward</h2>
<p>Despite some limitations, the Deno team's rapid improvements and community engagement are impressive. While I'm currently limited to reporting issues<a target="_blank" href="https://github.com/denoland/deno/issues?q=+is%3Aissue+author%3Ayasaichi+">^3</a>, I hope to contribute more directly to the runtime's evolution through code in the future.</p>
<p>For developers considering Deno in production, my advice is to approach it with cautious optimism. The runtime shows immense promise, and its evolving trajectory offers an exciting alternative for modern JavaScript development.</p>
]]></content:encoded></item><item><title><![CDATA[Presentation: JSConf JP 2024]]></title><description><![CDATA[Deck


https://decks.yasaichi.com/20241123/type-safe-lightweight-ddd-with-effect-schema
Abstract
At EARTHBRAIN, we have adopted "Effect," an emerging TypeScript library, to develop an API gateway. This innovative library can separate main concerns fr...]]></description><link>https://blog.yasaichi.com/jsconf-jp-2024</link><guid isPermaLink="true">https://blog.yasaichi.com/jsconf-jp-2024</guid><category><![CDATA[jsconf]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[effect]]></category><category><![CDATA[effect-ts]]></category><category><![CDATA[DDD]]></category><dc:creator><![CDATA[Yuichi Sato]]></dc:creator><pubDate>Mon, 25 Nov 2024 15:00:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-deck">Deck</h2>
<iframe src="https://decks.yasaichi.com/20241123/type-safe-lightweight-ddd-with-effect-schema"></iframe>

<p><a target="_blank" href="https://decks.yasaichi.com/20241123/type-safe-lightweight-ddd-with-effect-schema">https://decks.yasaichi.com/20241123/type-safe-lightweight-ddd-with-effect-schema</a></p>
<h2 id="heading-abstract">Abstract</h2>
<p>At EARTHBRAIN, we have adopted "Effect," an emerging TypeScript library, to develop an API gateway. This innovative library can separate main concerns from sub-concerns such as asynchronous and concurrent operations, error handling, and retry mechanisms, enhancing application robustness and scalability. However, as its core type is not a standard JavaScript type, you must carefully consider whether you can achieve the expected outcomes before adopting the library across the entire project.</p>
<p>This presentation will focus on the standard library-like aspects of Effect, exploring a pragmatic approach through a case study. Specifically, we will explore how to implement type-safe, lightweight Domain-Driven Design (DDD) using this library. Through this presentation, you will gain deeper insights into practical approaches leveraging advanced TypeScript technologies.</p>
]]></content:encoded></item></channel></rss>