<?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[$ tail ./x5gtrn.log]]></title><description><![CDATA[<p>I explore topics that interest me through explanatory slides and in-depth articles, sharing what I learn in the hope that others will find it useful.</p>
<p>Except for those in <a href="https://daisuke.masuda.tokyo/series/handcrafted"><b> Handcrafted</b></a>, all content on this site is created with the assistance of AI.</p>
]]></description><link>https://daisuke.masuda.tokyo</link><generator>RSS for Node</generator><lastBuildDate>Fri, 11 Sep 2026 08:14:30 GMT</lastBuildDate><atom:link href="https://daisuke.masuda.tokyo/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="first" href="https://daisuke.masuda.tokyo/rss.xml"/><atom:link rel="next" href="https://daisuke.masuda.tokyo/rss.xml?after=20"/><item><title><![CDATA[Manus in 2026: An Engineer's Guide to the Always-On AI Workspace]]></title><description><![CDATA[<p>In January 2026, I published <a href="https://daisuke.masuda.tokyo/article-2026-01-02-0324">a deep dive into Manus</a>. At the time, the interesting question was whether an AI agent could move beyond answering questions and complete a multi-step task inside its own cloud environment. Manus 1.6 Max, Wide Research, full-stack and mobile development, Design View, and the first generation of Scheduled Tasks made a strong case that it could.</p>
<p>Eight months later, that framing is no longer sufficient.</p>
<p>The most consequential Manus updates are not simply improvements to model quality. They change where work runs, what state survives, how an agent reuses team knowledge, when it may act without confirmation, and how generated software remains operational after the first build. Manus now spans temporary cloud machines, a user's local computer, persistent cloud infrastructure, project-scoped skills, external services, recurring execution, and native business artifacts.</p>
<p>That makes the current engineering question more demanding:</p>
<blockquote>
<p>Has Manus become an always-on engineering workspace, rather than an agent that completes isolated tasks?</p>
</blockquote>
<p>The answer is qualified. The product now contains many of the components of such a workspace. But those components do not erase the engineering responsibilities around permissions, state, observability, backup, failure recovery, and cost. They move those responsibilities to new boundaries.</p>
<p>This article maps those boundaries as of <strong>September 8, 2026</strong>. It separates documented product behavior from the operational claims that teams should still validate themselves.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/manus-2026-update">https://speakerdeck.com/x5gtrn/manus-2026-update</a></p>

<h2>The January baseline has changed</h2>
<p>The January article described Manus as an autonomous agent with a planning layer, an execution core, and access to tools such as a browser, shell, and file system. That model remains useful, but it assumes that the main unit of work is a task: the user supplies a goal, Manus creates a plan, the agent executes it, and the user receives an artifact.</p>
<p>The 2026 releases added several longer-lived units around that task:</p>
<ul>
<li><p>an execution environment that can survive across tasks;</p>
</li>
<li><p>a local execution path into the developer's own machine;</p>
</li>
<li><p>project instructions and reusable Skills;</p>
</li>
<li><p>schedules that return to an existing context;</p>
</li>
<li><p>connectors that can update external systems, rather than merely read them;</p>
</li>
<li><p>hosting and publishing workflows that continue after generation;</p>
</li>
<li><p>explicit planning, branching, approval, and rollback controls.</p>
</li>
</ul>
<p>There is also an important corporate correction. My January article discussed Manus after Meta's December 2025 acquisition. Manus subsequently announced its <a href="https://manus.im/blog/a-note-to-our-users">separation from Meta and a backup-and-restoration process for affected users</a>, and on September 1 announced that it had <a href="https://manus.im/blog/manus-resumes-independent-operations">formally resumed independent operations</a>. The earlier article remains a snapshot of its publication date, but its Meta-era assumptions should not be projected onto the current product.</p>
<h2>Start with the execution environment</h2>
<p>The cleanest way to understand modern Manus is to stop thinking of it as one computer. It now exposes three materially different execution environments.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/57e43f59-9ae1-4d58-80ba-3baf0c737ba8.jpg" alt="" style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th>Environment</th>
<th>State model</th>
<th>Best fit</th>
<th>Primary dependency</th>
<th>Main operational concern</th>
</tr>
</thead>
<tbody><tr>
<td>Temporary Sandbox</td>
<td>Task-scoped and recyclable</td>
<td>Research, code generation, analysis, documents, short builds</td>
<td>Manus-managed virtual machine</td>
<td>Intermediate files may disappear after recycling</td>
</tr>
<tr>
<td>My Computer</td>
<td>Persistent because it is your machine</td>
<td>Local repositories, desktop apps, local toolchains and hardware</td>
<td>Your computer must be available and authorized</td>
<td>The agent can affect real local data</td>
</tr>
<tr>
<td>Cloud Computer</td>
<td>Persistent and designed to remain online</td>
<td>Bots, scheduled jobs, databases, APIs and self-hosted tools</td>
<td>Paid cloud capacity and remote credentials</td>
<td>Backup, patching, secrets, uptime and lifecycle ownership</td>
</tr>
</tbody></table>
<p>Choosing among these is an architecture decision. A prompt that asks Manus to run this every morning is incomplete until the team decides where the executable, state, credentials, logs, and outputs will live.</p>
<h3>Temporary Sandbox: disposable compute with selective restoration</h3>
<p>The <a href="https://manus.im/blog/manus-sandbox">Manus Sandbox</a> is an isolated virtual machine allocated to a task. It includes networking, a file system, a browser, command-line tools, and the ability to execute code. Separate tasks receive separate environments and can run in parallel.</p>
<p>The important detail is its lifecycle. The Sandbox can sleep and wake without changing its files, but an inactive Sandbox may eventually be recycled. Manus currently documents a seven-day inactive retention period for Free users and 21 days for Pro users. When Manus recreates a recycled Sandbox, it restores uploaded attachments, Manus artifacts, and selected project files, but it does not promise to restore every intermediate script or temporary file.</p>
<p>That distinction should change how an engineer uses it.</p>
<p>Good Sandbox workloads include:</p>
<ul>
<li><p>investigating a library and delivering a report;</p>
</li>
<li><p>transforming a dataset into a reviewed spreadsheet;</p>
</li>
<li><p>generating a disposable prototype;</p>
</li>
<li><p>reproducing a bug in an isolated environment;</p>
</li>
<li><p>building an artifact whose source is exported at the end of the task.</p>
</li>
</ul>
<p>A poor Sandbox workload is a service whose correctness depends on an unexported working directory still existing next month.</p>
<p>Treat the Sandbox like an ephemeral CI runner. Export source code, manifests, lockfiles, migrations, and important logs. If an artifact matters, put it in a system with an explicit retention policy rather than assuming the conversational workspace is the system of record.</p>
<p>The same documentation exposes a subtle collaboration boundary. Sharing a task exposes the conversation and output artifacts, while collaboration allows participants to issue instructions that can affect the Sandbox. Manus says connectors are disabled when collaboration is enabled. That is a useful safeguard, but it does not make arbitrary files inside a collaborative Sandbox harmless. A task containing credentials, customer exports, or private source code should be reviewed before collaborators are invited.</p>
<h3>My Computer: the trust boundary moves onto your machine</h3>
<p><a href="https://manus.im/blog/manus-my-computer-desktop">My Computer</a> is part of Manus Desktop. It lets the agent issue command-line instructions on the user's Mac or Windows machine, read and edit authorized local files, and launch or control local applications.</p>
<p>This solves a real limitation of cloud agents. Your working repository, Xcode project, Docker cache, local database, signing configuration, and specialized hardware may not exist in a hosted sandbox. Moving the agent to the repository can be more practical than copying the repository to the agent.</p>
<p>It also makes the blast radius real.</p>
<p>According to Manus, terminal commands require explicit approval. The user may approve once or choose an Always Allow path for trusted work. The second option improves throughput, but it is a security decision, not a convenience toggle. The correct question is not whether the agent is generally trustworthy. It is whether a specific command class, in a specific directory, using a specific account, has an acceptable failure radius.</p>
<p>For repository work, I would start with constraints like these:</p>
<pre><code class="language-text">Work only inside /Users/me/projects/example-app.
Do not read .env, SSH configuration, browser profiles, or keychains.
Before installing software or running a command outside the repository,
show the exact command and explain why it is required.
Do not push, publish, delete branches, or modify cloud resources.
Run tests and produce a diff for review.
</code></pre>
<p>Natural-language constraints are not an operating-system sandbox, but they improve reviewability. Pair them with filesystem permissions, least-privilege credentials, version control, and backups.</p>
<p>My Computer is the right environment when the job inherently depends on local state. It is not the right answer for an unattended service unless you deliberately accept the availability of your laptop or dedicate an always-on machine to it. Manus itself notes that remote work depends on the computer being powered on and the Desktop application running.</p>
<h3>Cloud Computer: persistence changes the problem</h3>
<p>The <a href="https://manus.im/blog/manus-cloud-computer">Cloud Computer</a> is a dedicated, persistent Ubuntu environment designed for continuous operation. Manus positions it for 24/7 bots, databases, scheduled scrapers, APIs, persistent knowledge bases, and self-hosted software such as Metabase or WordPress. Users can access it through SSH or a web terminal, and the product exposes CPU, memory, and storage monitoring.</p>
<p>This is a more important change than another model upgrade. The agent can leave behind a running system, and later tasks can encounter the same files and installed tools. Work no longer has to end when the generating conversation ends.</p>
<p>Consider a dependency-monitoring service:</p>
<pre><code class="language-text">Create a service that checks the repositories listed in repos.yaml every day.
For each repository, fetch the current dependency lockfile, identify newly
published critical vulnerabilities, and write the results to PostgreSQL.
Send a Slack alert only for a new critical finding.

Before deployment, show me:
1. the architecture and threat model;
2. the database schema and retention policy;
3. every external credential and requested scope;
4. retry, timeout, and deduplication behavior;
5. backup and restore instructions;
6. estimated recurring cost.

Do not enable the schedule or send a message until I approve the plan.
</code></pre>
<p>The prompt is intentionally operational. Build a vulnerability bot describes a feature. It says nothing about idempotency, alert storms, secrets, backups, or failure recovery.</p>
<p>Persistent compute also creates persistent liabilities. The official Cloud Computer article says that upgrading a plan restarts the virtual machine, running projects pause during that restart, and working files are deleted if the subscription stops, although delivered outputs remain in chat history. It also states that the environment currently has no graphical desktop.</p>
<p>For production-like use, assume that the Cloud Computer is replaceable:</p>
<ul>
<li><p>keep application source in version control;</p>
</li>
<li><p>define the environment with a reproducible manifest or container configuration;</p>
</li>
<li><p>store secrets outside the repository and rotate them;</p>
</li>
<li><p>back up databases to a different failure domain;</p>
</li>
<li><p>export audit and application logs;</p>
</li>
<li><p>test restoration, not just backup creation;</p>
</li>
<li><p>document what happens when the subscription, account, or region changes.</p>
</li>
</ul>
<p>Cloud Computer reduces server setup work. It does not abolish server ownership.</p>
<h2>Planning and branching turn autonomy into a controlled process</h2>
<p>Early agent products optimized for immediate execution. That is impressive in demos and uncomfortable in systems where a plausible but incorrect assumption can produce a schema migration, publish a site, or message a customer.</p>
<p>Manus's newer controls acknowledge this tension.</p>
<h3>Plan Mode is an execution gate</h3>
<p><a href="https://manus.im/blog/manus-plan-mode">Plan Mode</a> expands a request into a Markdown plan containing goals, steps, and constraints. If important context is missing, the agent asks questions. The user can edit the plan directly or ask Manus to revise it.</p>
<p>The key behavior is simple: <strong>Manus does not begin the build until the plan is confirmed or dismissed.</strong> Plan Mode can also be activated during a task, allowing the user to pause execution and plan the next phase.</p>
<p>For engineering work, the plan should expose decisions that are expensive to discover after implementation:</p>
<ul>
<li><p>the data model and migration order;</p>
</li>
<li><p>authentication and authorization rules;</p>
</li>
<li><p>external APIs and credential scopes;</p>
</li>
<li><p>destructive or externally visible actions;</p>
</li>
<li><p>performance and availability assumptions;</p>
</li>
<li><p>deployment target and rollback path;</p>
</li>
<li><p>logging, metrics, and alerting;</p>
</li>
<li><p>acceptance criteria.</p>
</li>
</ul>
<p>Do not approve a plan because it looks detailed. Review it like a lightweight design document. A long plan can still omit the one invariant that matters.</p>
<h3>Branch is useful when the uncertainty is architectural</h3>
<p><a href="https://manus.im/blog/manus-branch">Branch</a> lets users explore multiple directions from a shared context. This is valuable when alternatives should inherit the same requirements and evidence but remain isolated from each other's decisions.</p>
<p>Examples include:</p>
<ul>
<li><p>a serverless implementation versus a persistent-service implementation;</p>
</li>
<li><p>row-level security in Supabase versus authorization in an application API;</p>
</li>
<li><p>a minimal internal tool versus a customer-facing product;</p>
</li>
<li><p>a conservative migration plan versus a faster plan with a maintenance window.</p>
</li>
</ul>
<p>The useful output is not two polished mockups. It is a decision record:</p>
<pre><code class="language-markdown">## Decision
Choose Branch B: application API owns authorization.

## Why
- centralizes policy enforcement;
- provides a stable audit point;
- avoids exposing database-specific rules to clients.

## Cost
- adds an operational service;
- increases latency;
- requires separate availability monitoring.

## Rejected alternative
Direct client access with row-level security remains appropriate for the
internal prototype, but not for the multi-tenant production design.
</code></pre>
<p>Copying and rollback controls complement branching. Branches help before a decision. Copies isolate an experiment. Rollback helps after a change fails. None replaces source control for code you must own outside the platform.</p>
<h2>Projects and Skills make process reusable</h2>
<p>Execution environments preserve compute state. Projects and Skills preserve working knowledge.</p>
<p>Manus announced support for the <a href="https://manus.im/blog/manus-skills">Agent Skills open standard</a>, which packages instructions, scripts, references, and assets as filesystem-based resources. The documented design uses progressive disclosure: metadata is available cheaply, the main instructions load when triggered, and supporting resources load only when referenced.</p>
<p>This is attractive to engineers because it turns part of the prompt into a versionable interface. A useful Skill can define:</p>
<ul>
<li><p>when it should run;</p>
</li>
<li><p>what inputs it accepts;</p>
</li>
<li><p>which tools it may use;</p>
</li>
<li><p>validation and security checks;</p>
</li>
<li><p>expected output files;</p>
</li>
<li><p>examples of acceptable and unacceptable results.</p>
</li>
</ul>
<p><a href="https://manus.im/blog/manus-project-skills">Project Skills</a> narrow that library to a project. Manus says that only Skills explicitly added to a Project are available there, and teams can lock the set to prevent accidental workflow changes. That reduces the chance that an unrelated personal Skill silently changes a team process.</p>
<p>Projects can now also <a href="https://manus.im/blog/manus-projects-self-updating">propose updates from completed conversations</a>. Manus may identify reusable terminology, examples, source files, instructions, or workflow patterns and suggest changes to Project context or Skills. The product documentation is explicit that those changes require user approval.</p>
<p>This should not be described as the model learning your company in the machine-learning sense. A more accurate mental model is a governed knowledge-maintenance loop:</p>
<ol>
<li><p>a task produces a useful decision or procedure;</p>
</li>
<li><p>Manus identifies a reusable change;</p>
</li>
<li><p>a human reviews the proposed diff;</p>
</li>
<li><p>the Project stores the approved instruction, file, or Skill;</p>
</li>
<li><p>later tasks start with the updated context.</p>
</li>
</ol>
<p>The engineering opportunity is significant, but so is configuration drift. Treat Project instructions and Skills like code. Assign owners, review changes, keep examples, test important workflows, and retain a history that explains why a rule exists.</p>
<h2>Scheduled Tasks 2.0 is about context, not only time</h2>
<p>The first version of Scheduled Tasks repeated work on a clock. <a href="https://manus.im/blog/manus-schedules">Scheduled Tasks 2.0</a> adds a second dimension: where the recurring work continues.</p>
<p>A run can return to the same task and reuse its conversation, files, instructions, and results. A schedule associated with a Project can use that Project's files, Skills, connectors, and output conventions. Manus-built web applications can also contain scheduled actions for data refreshes, scripts, reminders, dashboards, or recurring summaries.</p>
<p>The official explanation captures the design change well: The schedule follows the place where the work lives, not just the time on the calendar.</p>
<p>That is closer to a stateful workflow engine than a prompt attached to cron. It also inherits familiar workflow-engine failure modes:</p>
<ul>
<li><p>a retry duplicates an external action;</p>
</li>
<li><p>stale context changes the meaning of a later run;</p>
</li>
<li><p>a connector token expires;</p>
</li>
<li><p>a partial run updates the database but fails before notification;</p>
</li>
<li><p>the schedule succeeds technically while producing incorrect content;</p>
</li>
<li><p>a long-running task overlaps its next invocation.</p>
</li>
</ul>
<p>Manus exposes run history, upcoming schedules, and options to continue in the same task or create a separate task. It also offers Skip confirmations for trusted workflows, including sending, publishing, or posting.</p>
<p>That switch deserves a production review. A read-only morning digest and an automated customer email should not share the same approval policy. Classify scheduled operations by effect:</p>
<table>
<thead>
<tr>
<th>Effect</th>
<th>Example</th>
<th>Suggested default</th>
</tr>
</thead>
<tbody><tr>
<td>Read</td>
<td>Collect public release notes</td>
<td>May run unattended</td>
</tr>
<tr>
<td>Internal write</td>
<td>Update a draft dashboard</td>
<td>Run unattended with history and rollback</td>
</tr>
<tr>
<td>External write</td>
<td>Modify a CRM record</td>
<td>Require narrow scopes, validation and audit</td>
</tr>
<tr>
<td>Communication</td>
<td>Send email or Slack message</td>
<td>Draft first or restrict recipients and templates</td>
</tr>
<tr>
<td>Destructive action</td>
<td>Delete, revoke or overwrite</td>
<td>Keep explicit approval unless a tightly tested runbook exists</td>
</tr>
</tbody></table>
<p>For each schedule, define an idempotency key, retry ceiling, timeout, alert destination, owner, and disable procedure. If the interface does not expose one of these controls, implement it in the workload or treat the gap as an adoption blocker.</p>
<h2>Connectors turn context into authority</h2>
<p>The growing connector catalog is easy to present as a wall of logos. For engineers, the important distinction is what authority each connector grants.</p>
<p>A connector may allow Manus to:</p>
<ol>
<li><p>retrieve information;</p>
</li>
<li><p>update existing data;</p>
</li>
<li><p>create a new artifact;</p>
</li>
<li><p>send or publish something externally.</p>
</li>
</ol>
<p>Those are different risk levels even when they belong to the same service.</p>
<p>The upgraded <a href="https://manus.im/blog/manus-google-drive-connector-update-cli">Google Workspace connector</a>, for example, is documented as supporting precise edits inside Docs, Sheets, and Slides rather than only creating or reading files. Manus describes actions such as replacing text in a specific section, updating speaker notes, duplicating a spreadsheet tab while retaining formulas, and replying to a document comment. The integration uses Google OAuth 2.0 permissions and a Google Workspace CLI that Manus notes is open source but not an officially supported Google product.</p>
<p>The <a href="https://manus.im/blog/manus-supabase-connector">Supabase connector</a> goes further into operational data. Manus says it can query authorized projects, execute SQL, propose and apply schema migrations, deploy Edge Functions, inspect logs, and surface security or performance recommendations. The available actions depend on the Supabase access granted by the user and the Supabase plan.</p>
<p>A safe database prompt should separate proposal from mutation:</p>
<pre><code class="language-text">Inspect the attached CRM export and the target Supabase schema.
Produce:
- a column mapping;
- rejected-row rules;
- deduplication keys;
- the proposed SQL migration;
- a dry-run report with row counts;
- rollback SQL.

Do not alter the schema or import records until I approve the migration.
After approval, execute inside a transaction where supported, validate counts,
sample the imported records, and save an audit report.
</code></pre>
<p>The <a href="https://manus.im/blog/elevenlabs-connector">ElevenLabs integration</a> illustrates a different boundary. Manus documents speech generation, transcription, voice cloning, and voice-enabled application development through an authorized ElevenLabs account. Billing and usage remain governed by that account, and voice cloning carries consent and rights obligations. The connector worked is not sufficient acceptance criteria when the output can impersonate a person.</p>
<p>For every connector, capture five facts before automation:</p>
<ul>
<li><p>exact OAuth scopes or API permissions;</p>
</li>
<li><p>which resources the authorization covers;</p>
</li>
<li><p>whether the agent can read, write, send, publish, or delete;</p>
</li>
<li><p>where inputs and outputs are processed and retained;</p>
</li>
<li><p>how access is revoked and how revocation affects scheduled work.</p>
</li>
</ul>
<p>The agent's reasoning quality does not compensate for an overprivileged token.</p>
<h2>Application generation now extends into operations</h2>
<p>The January view of Manus app development emphasized scaffolding and deployment. The newer product surface stretches across a larger lifecycle: planning, code generation, database integration, testing, <a href="https://manus.im/blog/manus-hosting-web-builder">multiple hosting modes</a>, <a href="https://manus.im/blog/manus-auto-publish">automatic publishing after changes</a>, analytics, scheduled behavior, and subsequent modification.</p>
<p>This can compress the distance from idea to a running internal tool. It can also conceal ownership questions. A generated application still needs answers to these:</p>
<ul>
<li><p>Where is the canonical source repository?</p>
</li>
<li><p>Who owns the domain and DNS configuration?</p>
</li>
<li><p>Where are production secrets stored?</p>
</li>
<li><p>Which component owns authentication and authorization?</p>
</li>
<li><p>Who applies dependency and operating-system updates?</p>
</li>
<li><p>Where are database backups stored?</p>
</li>
<li><p>What telemetry proves the application is healthy?</p>
</li>
<li><p>Can the team rebuild it outside the original Manus account?</p>
</li>
</ul>
<p>The <a href="https://manus.im/blog/manus-ppt-slides">native PowerPoint mode</a> is a smaller but revealing example of the same shift. Manus announced that PowerPoint mode creates <code>.pptx</code> files directly, including editable charts backed by data tables and structured table objects, rather than only converting a web presentation at export time. The July announcement described the feature as Beta for the 1.6 and Max models. Teams should recheck its current availability and still open generated files in PowerPoint to verify fonts, layout, charts, notes, and editability.</p>
<p>The principle is the same for code and documents: generation is not validation.</p>
<h2>A reference workflow for governed, continuous operation</h2>
<p>The pieces become clearer when assembled into one engineering workflow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/01213d84-7050-4206-a4a6-0bb1d6c55333.jpg" alt="" style="display:block;margin:0 auto" />

<p>Suppose a platform team wants a daily dependency-risk service.</p>
<h3>1. Put requirements behind Plan Mode</h3>
<p>Define repositories, severity policy, data sources, scan frequency, false-positive handling, alert recipients, and retention. Require approval before any connector, schedule, database, or outbound message is enabled.</p>
<h3>2. Use Branch for the costly uncertainty</h3>
<p>Compare a fully managed implementation with a Cloud Computer service. Measure operational control, data retention, portability, and recurring cost. Do not branch merely to produce two visual designs.</p>
<h3>3. Select the execution environment explicitly</h3>
<p>Use a temporary Sandbox to explore APIs and produce a prototype. Use My Computer only if the scanner must access local repositories or proprietary local tooling. Use Cloud Computer if the approved design needs continuous uptime and persistent state.</p>
<h3>4. Package the workflow as a Project Skill</h3>
<p>Store source-quality rules, severity thresholds, required report fields, validation steps, and the notification template. Lock the Project Skill after review if consistency matters more than ad hoc customization.</p>
<h3>5. Authorize narrow connectors</h3>
<p>Grant read access to the required repositories and the minimum Slack capability needed for the approved destination. Separate a credential that reads vulnerability data from one that sends notifications.</p>
<h3>6. Add the schedule last</h3>
<p>Implement deduplication and dry-run behavior first. Run manually against representative data. Confirm failure alerts and recovery. Only then create the recurring schedule and decide whether confirmations may be skipped.</p>
<h3>7. Feed learning back through review</h3>
<p>After several runs, ask Manus to propose improvements to the Project instructions or Skill. Review the change as you would review a pull request. Do not let a one-off incident silently redefine the permanent workflow.</p>
<p>This process is less magical than tell the agent what outcome you want. It is also much closer to how reliable systems are built.</p>
<h2>What I would verify before enterprise adoption</h2>
<p>The slide deck that motivated this article ends with constraints to verify. That is the right ending, because many official pages describe capability, not a service-level objective.</p>
<p>I would run a two-week evaluation with evidence in these areas:</p>
<h3>Reliability</h3>
<ul>
<li><p>task completion rate for a fixed suite of representative workflows;</p>
</li>
<li><p>schedule start delay and end-to-end duration;</p>
</li>
<li><p>behavior after transient network, connector, and model failures;</p>
</li>
<li><p>duplicate side effects after retry;</p>
</li>
<li><p>overlapping-run behavior;</p>
</li>
<li><p>recovery after Cloud Computer restart.</p>
</li>
</ul>
<h3>State and portability</h3>
<ul>
<li><p>which Sandbox files survive sleep and recycling;</p>
</li>
<li><p>complete rebuild of a Cloud Computer from versioned configuration;</p>
</li>
<li><p>database backup and restore into a separate environment;</p>
</li>
<li><p>artifact export without access to the originating task;</p>
</li>
<li><p>account and subscription termination behavior.</p>
</li>
</ul>
<h3>Security and governance</h3>
<ul>
<li><p>connector scopes and revocation;</p>
</li>
<li><p>local folder and command approvals in My Computer;</p>
</li>
<li><p>collaboration access to task files;</p>
</li>
<li><p>auditability of external writes;</p>
</li>
<li><p>approval behavior for Plan Mode and scheduled tasks;</p>
</li>
<li><p>secrets exposure in logs, artifacts, prompts, and generated code.</p>
</li>
</ul>
<h3>Quality and cost</h3>
<ul>
<li><p>credits or subscription cost per successful workflow;</p>
</li>
<li><p>human review time, not only agent runtime;</p>
</li>
<li><p>defect rate in code, data changes, and documents;</p>
</li>
<li><p>editability of generated PowerPoint files;</p>
</li>
<li><p>rework caused by incorrect assumptions;</p>
</li>
<li><p>cost of persistent Cloud Computer capacity and external services.</p>
</li>
</ul>
<p>Record the denominator. Eight tasks succeeded is weak evidence if the team attempted 30 and manually rescued half of them. Measure successful, reviewable outcomes, not attractive first drafts.</p>
<h2>The practical conclusion</h2>
<p>Manus in September 2026 is meaningfully broader than the Manus I described in January. It has three execution models, explicit pre-execution planning, parallel branches, reusable and project-scoped Skills, context-aware schedules, connectors with write authority, persistent cloud compute, and richer operational paths for applications and content.</p>
<p>That is enough to call it an <strong>AI workspace for continuous operations</strong> as a product direction.</p>
<p>It is not enough to assume that every workload placed inside it is production-ready. The platform can generate code, hold state, operate external services, and act on a schedule. Those abilities make conventional engineering controls more important, not less.</p>
<p>The teams that benefit most will not be those that write the cleverest one-shot prompt. They will be the teams that make the execution environment explicit, narrow authority, review plans, preserve state intentionally, test failure paths, and keep a human accountable for every system allowed to act continuously.</p>
<p>That is the real shift since January. Manus is no longer interesting only because it can finish a task. It is interesting because it can keep working after the task should have ended.</p>
<p>And that is precisely when engineering begins.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-09-08-2102</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-09-08-2102</guid><category><![CDATA[ai agents]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[automation]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[manus]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Where Is JetBrains AI Heading?]]></title><description><![CDATA[<p>AI coding tools are usually compared as if they were interchangeable chat boxes: Which model scores higher? Which agent edits more files? Which subscription is cheaper?</p>
<p>JetBrains appears to be asking a more architectural question: <strong>What has to surround an agent before it can become a dependable part of software delivery?</strong></p>
<p>The answer emerging across JetBrains AI Assistant, the Agent Client Protocol (ACP), the Model Context Protocol (MCP), JetBrains Central CLI, JetBrains Context, Air, and Central Console is not one super-agent. It is a stack of separable layers:</p>
<ul>
<li><p>a place where developers work;</p>
</li>
<li><p>one or more agents that plan and execute;</p>
</li>
<li><p>protocols that connect agents, clients, and tools;</p>
</li>
<li><p>repository intelligence that improves retrieval;</p>
</li>
<li><p>routing, identity, credits, policy, and analytics;</p>
</li>
<li><p>verification and human review across the entire system.</p>
</li>
</ul>
<p>That direction matters because teams do not merely need another way to generate code. They need a way to let developers choose agents without rebuilding every integration, let agents reach useful tools without receiving unlimited authority, and let an organization understand cost without pretending that cost telemetry proves code quality.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/where-is-jetbrains-ai-heading-central-cli-air-alpha-and-the-agentic-development-stack">https://speakerdeck.com/x5gtrn/where-is-jetbrains-ai-heading-central-cli-air-alpha-and-the-agentic-development-stack</a></p>

<p>This article develops that model from an engineer's perspective. It explains which component solves which problem, shows how the pieces interact, and proposes a practical adoption plan with explicit boundaries and measurable exit criteria.</p>
<blockquote>
<p><strong>Snapshot date: September 7, 2026.</strong> JetBrains is shipping these products at different maturity levels. Air is currently a Public Preview, Central CLI and JetBrains Context are Early Access offerings, and several Central governance capabilities continue to evolve. Verify the linked product documentation before making production, licensing, or compliance decisions.</p>
</blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/90f238e8-efc2-4734-9309-ed7adedfe48f.png" alt="" style="display:block;margin:0 auto" />

<p><em>A useful mental model is a layered stack, not a single AI product. Human review is a cross-cutting control, not the final box in a linear pipeline.</em></p>
<h2>The thesis: connection, not replacement</h2>
<p>The most important point is easy to miss: these products do not replace one another.</p>
<p>AI Assistant remains the in-IDE surface for chat, completion, edits, and integrated agents. ACP lets an IDE or another client communicate with external coding agents. MCP lets an AI application call external tools and access data. Central CLI routes supported terminal agents through JetBrains Central. JetBrains Context supplies semantic repository retrieval. Air provides an agent-first workspace for parallel tasks and review. Central Console supplies organization-level access, credits, and analytics.</p>
<p>The boundaries can be summarized like this:</p>
<table>
<thead>
<tr>
<th>Component</th>
<th>Primary job</th>
<th>What it is not</th>
</tr>
</thead>
<tbody><tr>
<td>AI Assistant</td>
<td>In-IDE assistance and agent access</td>
<td>An organization-wide CLI traffic plane</td>
</tr>
<tr>
<td>ACP</td>
<td>Agent-to-client interoperability</td>
<td>A tool/data protocol or billing system</td>
</tr>
<tr>
<td>MCP</td>
<td>Model access to tools and data</td>
<td>An agent UI or orchestration product</td>
</tr>
<tr>
<td>Central CLI</td>
<td>Routing supported terminal agents through Central</td>
<td>A replacement coding agent</td>
</tr>
<tr>
<td>JetBrains Context</td>
<td>Semantic repository intelligence</td>
<td>A terminal-agent proxy</td>
</tr>
<tr>
<td>Air</td>
<td>Agent-first task, workspace, and review experience</td>
<td>A traditional IDE replacement for every workflow</td>
</tr>
<tr>
<td>Central Console</td>
<td>Access, credit controls, and analytics</td>
<td>Proof that generated code is correct</td>
</tr>
</tbody></table>
<p>This separation is healthy. A team can adopt one layer without accepting every other JetBrains product. A developer might use Codex in a terminal through Central CLI, query repository knowledge from JetBrains Context, and still review the patch in IntelliJ IDEA. Another team might use Air with its own provider credentials and an ACP-compatible agent. The architecture is valuable precisely when these combinations remain possible.</p>
<h2>A six-layer model for the JetBrains agentic stack</h2>
<p>The diagram above compresses the system into six concerns. They are worth examining separately because each has different failure modes, owners, and maturity requirements.</p>
<h3>1. Work surfaces: IDE, terminal, and agent cockpit</h3>
<p>The work surface is where a human starts, steers, and reviews a task.</p>
<p>For short, code-local work, the IDE is still difficult to beat. AI Assistant can combine a prompt with the active file, selection, diagnostics, navigation, and the rest of the IntelliJ code model. JetBrains documents integrated agents as separate execution choices and also supports external agents through ACP in <a href="https://www.jetbrains.com/help/ai-assistant/agents.html">AI Assistant</a>.</p>
<p>The terminal optimizes for composability. Developers can pipe data, reuse shell state, run an agent over SSH, or embed commands in scripts. Central CLI deliberately preserves that interface: after an agent is wired, the developer still invokes <code>claude</code>, <code>codex</code>, or <code>gemini</code> in the usual way. The route changes; the working habit does not.</p>
<p>Air addresses a different problem. JetBrains describes it as an agentic development environment where developers can run multiple agents concurrently, isolate tasks in containers or Git worktrees, provide precise code references, and review changes in repository context. The important distinction is not "IDE versus no IDE." Air places the task and the agent at the center, while a traditional IDE places the editable codebase at the center. JetBrains explicitly positions the two as complementary in the <a href="https://blog.jetbrains.com/air/2026/03/air-launches-as-public-preview-a-new-wave-of-dev-tooling-built-on-26-years-of-experience/">Air Public Preview announcement</a>.</p>
<p>Choose the surface according to the dominant interaction:</p>
<ul>
<li><p>use the IDE when you are coding and occasionally delegate;</p>
</li>
<li><p>use the terminal when you need composability, remote operation, or an existing CLI workflow;</p>
</li>
<li><p>use Air when you are supervising several agent tasks and comparing their results.</p>
</li>
</ul>
<h3>2. Agent layer: execution remains plural</h3>
<p>JetBrains is not betting that one agent will win every workload. AI Assistant and Air expose multiple agents, and the exact list is already changing. That is a realistic response to a fast market: model quality, price, latency, context behavior, and enterprise approval can all change faster than an IDE release cycle.</p>
<p>Agent plurality creates two engineering requirements.</p>
<p>First, tasks must have portable acceptance criteria. "Make this better" depends heavily on the agent's habits. A task such as the following is much easier to compare:</p>
<pre><code class="language-text">Refactor the retry policy behind the PaymentGateway interface.

Constraints:
- Preserve the public API.
- Do not modify database migrations or deployment manifests.
- Retry only idempotent operations.

Done when:
- Existing unit and integration tests pass.
- New tests cover timeout, 429, and non-retryable 4xx behavior.
- The patch introduces no new static-analysis warnings.
- A human reviewer approves the behavior and failure messages.
</code></pre>
<p>Second, teams must measure the whole run, not only the model call. The useful unit is an accepted engineering outcome: agent time, human attention, retries, tool failures, CI results, review findings, and cost. A model that is 30% cheaper per token but requires two rescue attempts may be the expensive choice.</p>
<h3>3. Connection layer: ACP, MCP, and Central CLI solve different problems</h3>
<p>The acronyms are similar enough to cause confusion, so use a simple test:</p>
<ul>
<li><p><strong>ACP connects a coding agent to a client such as an IDE or Air.</strong></p>
</li>
<li><p><strong>MCP connects an AI application to tools and data.</strong></p>
</li>
<li><p><strong>Central CLI connects supported terminal-agent traffic to JetBrains Central.</strong></p>
</li>
</ul>
<p><a href="https://agentclientprotocol.com/get-started/introduction">ACP</a> standardizes communication between editors and coding agents, much as the Language Server Protocol standardized editor-to-language-server integration. A local ACP agent can run as a subprocess and communicate over JSON-RPC through standard input/output. The protocol includes agentic UI concepts such as session updates, tool calls, permissions, and diffs. That lets a client present an agent's activity without implementing a proprietary integration for each agent.</p>
<p>MCP faces the other direction. A model or agent needs access to issue trackers, databases, browsers, build services, internal APIs, or IDE operations. JetBrains AI Assistant can connect to MCP servers, and JetBrains documents both user configuration and centrally managed server availability in its <a href="https://www.jetbrains.com/help/ai-assistant/mcp.html">MCP guide</a>.</p>
<p>Central CLI is neither of those protocols. It is a routing proxy. The official <a href="https://www.jetbrains.com/help/central-cli/quickstart.html">Central CLI quickstart</a> currently lists Claude Code, Codex, and Gemini CLI as supported wiring targets. It updates the agent's configuration so requests go through a local Central proxy, which then handles JetBrains authentication and routing to the cloud service.</p>
<p>These three mechanisms can coexist in one task:</p>
<pre><code class="language-text">Developer
  -&gt; Air or an IDE
     -&gt; ACP
        -&gt; Coding agent
           -&gt; MCP
              -&gt; IDE tools, issue tracker, CI, documentation

Developer
  -&gt; terminal agent command
     -&gt; Central CLI local proxy
        -&gt; JetBrains Central routing, credits, and telemetry
</code></pre>
<p>The first flow is about interaction and capabilities. The second is about traffic routing and management. Conflating them leads to incorrect security reviews. An agent can be beautifully integrated through ACP yet bypass Central CLI billing. An agent can be wired through Central CLI yet still have dangerously broad MCP tools.</p>
<h3>4. Knowledge layer: repository context is a retrieval system</h3>
<p>Agents spend a surprising amount of their budget rediscovering the codebase: searching for symbols, opening nearby files, locating an implementation pattern, and tracing dependencies. Larger context windows help, but loading more files is not the same as finding the right files.</p>
<p><a href="https://blog.jetbrains.com/ai/2026/07/introducing-jetbrains-context-repository-intelligence-for-coding-agents/">JetBrains Context</a> adds a semantic repository index for agents including Claude Code, Codex CLI, and Junie CLI. It is intended to work across JetBrains IDEs, Air, VS Code, and other supported environments. JetBrains reports reductions of up to 68% in agent turns, 59% in latency, and 48% in execution cost across its evaluation sets. Those are vendor-reported maxima, not guarantees; reproduce them on your own repositories before building a business case.</p>
<p>The privacy details deserve more attention than the headline numbers. Current <a href="https://www.jetbrains.com/help/jetbrains-console/getting-started-with-jetbrains-context.html">JetBrains Context documentation</a> says source chunks are sent to the service during indexing, where embeddings are computed and stored along with file paths, offsets, and repository and revision identifiers. Raw source is not stored as raw source; searches return coordinates, and the local client opens the corresponding code. The same documentation describes <code>jbcontext remove-index</code> for deleting indexed data.</p>
<p>For an enterprise review, "raw source is not stored" is only the beginning. Ask:</p>
<ol>
<li><p>Which repositories may be indexed?</p>
</li>
<li><p>Are generated files, secrets, fixtures, and regulated data excluded before chunking?</p>
</li>
<li><p>Which identities can query which repository indexes?</p>
</li>
<li><p>How quickly do access revocation and index deletion take effect?</p>
</li>
<li><p>Can the organization audit indexing, searches, and cross-repository retrieval?</p>
</li>
<li><p>What happens when repository permissions differ from Central permissions?</p>
</li>
</ol>
<p>Repository intelligence is powerful because it can cross local checkout boundaries. That same capability makes authorization correctness non-negotiable.</p>
<h3>5. Management layer: shared credits and visibility</h3>
<p>Once developers use several agents across IDEs, terminals, and Air, per-vendor dashboards stop answering basic questions. Who used the capacity? Which agent drove a spend spike? Did a trial create accepted patches or merely more messages?</p>
<p>Central Console attempts to provide one control and reporting plane. Its current <a href="https://www.jetbrains.com/help/jetbrains-console/ai-management.html">AI management documentation</a> covers AI-enabled licenses, included quota, top-up credits, and per-user limits. The <a href="https://www.jetbrains.com/help/jetbrains-console/ai-credits-consumption.html">AI Credits consumption report</a> aggregates supported-agent usage across AI Assistant, Central CLI, and Air.</p>
<p>The Session Explorer is especially useful - and easy to overinterpret. It can show attributable sessions with user, agent, model, duration, tokens, and credits. But JetBrains explicitly documents important gaps: updates are batched rather than real time; non-agentic AI Assistant features are excluded; and the explorer currently does not show MCP tool usage or repositories accessed per session. Read the limitations in the <a href="https://www.jetbrains.com/help/jetbrains-console/session-explorer.html">Session Explorer documentation</a> before treating it as a complete audit trail.</p>
<p>This produces a clean responsibility split:</p>
<table>
<thead>
<tr>
<th>Question</th>
<th>Best evidence</th>
</tr>
</thead>
<tbody><tr>
<td>What did the run cost?</td>
<td>Credit and token telemetry</td>
</tr>
<tr>
<td>Which agent/model ran?</td>
<td>Attributable session metadata</td>
</tr>
<tr>
<td>Which files changed?</td>
<td>Git diff and worktree history</td>
</tr>
<tr>
<td>Which tools were called?</td>
<td>Agent and MCP audit logs</td>
</tr>
<tr>
<td>Is the patch correct?</td>
<td>Tests, static analysis, runtime checks, and review</td>
</tr>
<tr>
<td>Was the action authorized?</td>
<td>Identity, policy decision, approval, and tool logs</td>
</tr>
</tbody></table>
<p>Cost visibility is necessary governance. It is not quality assurance.</p>
<h3>6. Verification and review: the vertical safety rail</h3>
<p>The final layer should not sit at the bottom of the stack. Verification must cross every layer:</p>
<ul>
<li><p>the surface should show the real diff and relevant diagnostics;</p>
</li>
<li><p>the agent should expose progress, tool calls, and permission requests;</p>
</li>
<li><p>the connection layer should preserve identity and auditability;</p>
</li>
<li><p>repository retrieval should respect authorization and revision boundaries;</p>
</li>
<li><p>management should report costs without obscuring execution evidence;</p>
</li>
<li><p>humans should make high-impact decisions with reproducible evidence.</p>
</li>
</ul>
<p>This is why Air's emphasis on worktrees, containers, contextual diffs, and review is more significant than its visual design. Parallelism without isolation creates conflicts. Isolation without an understandable review path creates abandoned patches. Review without tests becomes aesthetic approval.</p>
<p>Use the following loop as the minimum viable agent workflow:</p>
<pre><code class="language-text">inspect -&gt; propose -&gt; change -&gt; test -&gt; observe -&gt; review -&gt; accept or revise
</code></pre>
<p>The loop should end on evidence, not on the agent saying "done."</p>
<h2>Central CLI in practice: keep the workflow, change the route</h2>
<p>Central CLI is the most immediately testable part of the stack because it is deliberately narrow. The current quickstart is essentially:</p>
<pre><code class="language-bash"># Download, inspect, and run the installer according to your security policy.

central login
central add claude
central add codex
central add gemini

central status
central quota
</code></pre>
<p>After wiring, the normal commands remain normal:</p>
<pre><code class="language-bash">claude "explain this module"
codex "refactor this function"
gemini "review this change"
</code></pre>
<p>Under the hood, Central CLI runs a local proxy. JetBrains' troubleshooting documentation identifies port <code>19515</code> for the OAuth callback and <code>19516</code> as the default proxy port. It also shows that wiring changes each agent's provider or base URL configuration. That detail has four operational consequences.</p>
<h3>Treat wiring as a configuration change</h3>
<p>Before a pilot, record the existing agent configuration and provider behavior. After wiring, verify the expected base URL without printing the embedded secret. Run <code>central status</code>, open a fresh terminal, and execute a harmless read-only task. If you later remove the pilot, verify that the original provider route is restored rather than assuming an uninstall reverted configuration.</p>
<h3>Detect route bypass</h3>
<p>A dashboard can only govern traffic that passes through its route. Environment variables, per-project configuration, a container image, or an alternate binary may silently bypass the local proxy. Build a canary check that confirms the effective provider host for each managed agent while redacting credentials.</p>
<h3>Separate availability from agent correctness</h3>
<p>If the local proxy is down, the agent may fail even when the upstream provider is healthy. Central CLI's <a href="https://www.jetbrains.com/help/central-cli/troubleshooting.html">troubleshooting guide</a> recommends checking proxy status, opening a new terminal after configuration changes, and inspecting the agent's effective configuration. Monitor the proxy as a dependency; do not label every connection failure "the model is down."</p>
<h3>Review the data path and terms</h3>
<p>The Central CLI EAP terms state that cloud-routed use can transmit prompts, outputs, and workspace metadata through JetBrains services and downstream AI providers, while BYOK behavior has its own direct-provider path. They also place responsibility for generated output and local autonomous actions on the user. The exact legal and technical wording can change, so security and legal reviewers should use the current <a href="https://www.jetbrains.com/legal/docs/terms/jetbrains-central-cli-eap/">Central CLI EAP agreement</a> and service-provider list rather than a slide or blog summary.</p>
<h2>Air is a parallel-work system, not just another chat UI</h2>
<p>Air's useful abstraction is the task workspace. A task can run locally, in a Git worktree, or in an isolated container, while the human switches to another task. This makes parallel development visible without requiring one terminal window per agent.</p>
<p>The design suggests a practical operating model:</p>
<ol>
<li><p><strong>One task, one isolated workspace.</strong> Do not let three agents edit the same checkout.</p>
</li>
<li><p><strong>One explicit goal.</strong> A task should have a narrow output and executable acceptance checks.</p>
</li>
<li><p><strong>One evidence bundle.</strong> Preserve the diff, test results, diagnostics, and material tool activity.</p>
</li>
<li><p><strong>One accountable reviewer.</strong> Parallel work still needs a named human decision maker.</p>
</li>
<li><p><strong>Merge through the normal path.</strong> Agent output should enter the same branch protection and CI gates as human output.</p>
</li>
</ol>
<p>ACP is what makes the agent selection less tightly coupled to the surface. JetBrains and Zed designed ACP so a compatible client can talk to a compatible agent without a unique integration for every pair. Air now supports additional ACP-compatible agents and local-model arrangements, as described in JetBrains' <a href="https://blog.jetbrains.com/air/2026/07/what-s-new-air-gets-more-agents-local-models-and-java-kotlin-code-intelligence/">July 2026 Air update</a>.</p>
<p>Protocol compatibility, however, is not behavioral equivalence. Agents may expose different permission modes, context limits, resumption semantics, tool capabilities, and model choices. Pin ACP and agent versions during a pilot, test reconnect and cancellation behavior, and do not assume that a green "connected" indicator guarantees equivalent safety controls.</p>
<h2>A practical two-week evaluation</h2>
<p>The wrong pilot asks each agent to build a toy application. The right pilot samples work from your real backlog and freezes the acceptance criteria.</p>
<h3>Days 1-2: define boundaries and baselines</h3>
<p>Choose 12-20 tasks across four categories:</p>
<ul>
<li><p>deterministic maintenance, such as a rename or dependency update;</p>
</li>
<li><p>repository investigation, such as locating a production failure path;</p>
</li>
<li><p>feature work with integration tests;</p>
</li>
<li><p>review or documentation work that requires broad context.</p>
</li>
</ul>
<p>For each task, record a recent human-only baseline if one exists. Define repositories, branches, commands, external systems, data classifications, and actions that are allowed. Production deploys, external messages, credential changes, destructive operations, and security disclosures should normally remain approval-gated.</p>
<h3>Days 3-7: compare surfaces and routes</h3>
<p>Run the same task categories through the IDE, a terminal agent, and Air where appropriate. Do not force every task through every surface; the goal is to discover fit, not crown a universal winner.</p>
<p>Track:</p>
<pre><code class="language-text">verified_success_rate = accepted_tasks / attempted_tasks
attention_saved       = baseline_human_minutes - review_and_rescue_minutes
cost_per_accept        = total_credits_or_cost / accepted_tasks
false_completion_rate = failed_acceptance_checks / agent_claimed_completions
unsafe_action_rate     = policy_violations / attempted_tasks
</code></pre>
<p>Also record time to first useful diff, tool-call failures, test flakiness, merge conflicts, reviewer comments, and rollback effort. A task that succeeds only after the reviewer rewrites half the patch is not an agent success.</p>
<h3>Days 8-10: evaluate repository intelligence</h3>
<p>Select tasks that require cross-module or cross-repository discovery. Run them with and without JetBrains Context where practical. Measure files opened, search steps, agent turns, latency, cost, missed dependencies, and architecture conformity.</p>
<p>Do not test only happy paths. Include renamed symbols, duplicated implementations, stale documentation, generated code, and a repository the user is not authorized to query. Retrieval quality and access-control behavior matter together.</p>
<h3>Days 11-14: test governance and recovery</h3>
<p>Create controlled failures:</p>
<ul>
<li><p>stop the Central CLI proxy;</p>
</li>
<li><p>expire or revoke a test credential;</p>
</li>
<li><p>exhaust a small test credit limit;</p>
</li>
<li><p>deny an MCP permission;</p>
</li>
<li><p>cancel an Air task halfway through;</p>
</li>
<li><p>create a merge conflict in an isolated worktree;</p>
</li>
<li><p>remove a user's repository access and verify retrieval behavior.</p>
</li>
</ul>
<p>Then ask whether developers can diagnose the issue without an administrator, whether administrators can attribute cost, whether security can reconstruct significant actions, and whether the team can return to its original provider route.</p>
<p>The outcome of the pilot should be a decision per workflow, not a single adoption percentage.</p>
<h2>What JetBrains still has to prove</h2>
<p>The architecture is coherent, but architecture diagrams do not eliminate product risk.</p>
<h3>Interoperability needs conformance, not just support badges</h3>
<p>ACP can reduce integration cost, but the ecosystem needs reliable version negotiation, cancellation, permission semantics, resumption, diff fidelity, and remote-agent behavior. The <a href="https://github.com/agentclientprotocol/agent-client-protocol">ACP specification and SDK</a> are active projects. Enterprises should pin versions, maintain a small conformance suite, and treat draft protocol surfaces as changeable.</p>
<h3>Governance needs deeper execution evidence</h3>
<p>Credits and attributable sessions answer financial questions. They do not yet form a complete agent audit trail. JetBrains documents that Session Explorer does not currently expose MCP calls or repository access. Closing that gap - while controlling the sensitivity and retention of logs - will determine whether Central becomes a true engineering control plane or mainly a billing and adoption dashboard.</p>
<h3>Repository intelligence needs transparent authorization</h3>
<p>Cross-repository semantic search can save enormous time, but it must preserve repository-level identity, revision, and revocation semantics. Teams will need evidence that the retrieval layer cannot surface coordinates, paths, or patterns from repositories a user cannot access.</p>
<h3>Parallelism needs merge economics</h3>
<p>Running five agents is easy. Reviewing five overlapping patches is not. Air's worktree and review model is promising, but teams should measure conflict rate, reviewer queue time, abandoned-task rate, and accepted value per task - not the number of simultaneous sessions.</p>
<h3>Open choice must survive commercial pressure</h3>
<p>The strategic promise is agent and model choice with a shared management plane. That promise remains credible only if developers can change agents without losing essential context, permissions, observability, or cost controls, and if BYOK and managed-credit routes stay understandable.</p>
<h2>My take: JetBrains is building the connective tissue</h2>
<p>JetBrains' advantage is not that it can place another model behind an IDE chat window. Many vendors can do that.</p>
<p>Its stronger position is the connective tissue accumulated from decades of developer tooling: code models, navigation, diagnostics, refactoring, test integration, version control, workspaces, and now protocols, repository retrieval, and organization management. If JetBrains can expose those capabilities to multiple agents while keeping the human in a high-quality review loop, it can make the surrounding system more valuable than any single model subscription.</p>
<p>The emerging stack therefore looks less like a new IDE and more like an operating system for agentic development:</p>
<ul>
<li><p>AI Assistant is the in-editor entry point;</p>
</li>
<li><p>ACP makes agent clients and agents interchangeable enough to evolve independently;</p>
</li>
<li><p>MCP gives agents controlled access to useful capabilities;</p>
</li>
<li><p>Central CLI brings supported terminal traffic into a managed route;</p>
</li>
<li><p>Context gives agents a repository memory layer;</p>
</li>
<li><p>Air turns parallel agent work into visible, reviewable tasks;</p>
</li>
<li><p>Central Console gives organizations a place to manage access and economics;</p>
</li>
<li><p>tests, isolation, logs, and human review decide whether the output is trustworthy.</p>
</li>
</ul>
<p>That final line is the important one. No connection layer makes an agent correct. No dashboard makes a patch safe. No semantic index replaces authorization. No parallel workspace removes the cost of review.</p>
<p>Start with one bounded workflow. Keep the acceptance criteria executable. Route only the traffic you can verify. Grant the smallest useful tool surface. Measure accepted outcomes instead of generated tokens. Expand the blast radius only after the evidence says the system has earned it.</p>
<p>That is where JetBrains AI appears to be heading: not toward one agent that owns the entire workflow, but toward a stack in which developers can choose agents, organizations can govern the route, and humans can still understand and approve what reaches the codebase.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-09-07-0152</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-09-07-0152</guid><category><![CDATA[ai agents]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[software development]]></category><category><![CDATA[Jetbrains]]></category><category><![CDATA[Model Context Protocol]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Inside the Z.ai Engineering Stack: GLM-5.3, ZCode, and AutoClaw in Practice]]></title><description><![CDATA[<p>AI products are easier to evaluate when we stop treating them as interchangeable chat windows.</p>
<p>The Z.ai ecosystem is really three different engineering layers:</p>
<ol>
<li><p><strong>GLM-5.3</strong> is the model: it reasons, writes code, calls tools, and provides the context window.</p>
</li>
<li><p><strong>ZCode</strong> is the development harness: it turns model capability into a loop of inspecting, changing, running, and verifying software.</p>
</li>
<li><p><strong>AutoClaw</strong> is the work agent: it applies a similar loop to documents, browsers, data, and team messaging.</p>
</li>
</ol>
<p>That distinction matters. A benchmark can tell us something about a model, but it cannot tell us whether an agent has the right permissions, whether a browser task is observable, or whether the resulting patch passes our tests. The valueand much of the risklives in the whole system.</p>
<p>This article builds a practical mental model for the stack, shows concrete API and task patterns, and explains what I would measure before adopting it on a real engineering team.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/the-z-ai-ecosystem-in-practice-a-technical-reference-for-engineers">https://speakerdeck.com/x5gtrn/the-z-ai-ecosystem-in-practice-a-technical-reference-for-engineers</a></p>

<blockquote>
<p><strong>Snapshot date:</strong> August 24, 2026. Model availability, pricing, quotas, and product features change quickly; follow the linked official pages before making a purchase or production decision.</p>
</blockquote>
<h2>The stack in one picture</h2>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/ee438c62-a7f6-4cd0-91ce-9e1d191c5cdd.png" alt="" style="display:block;margin:0 auto" />

<p>The bottom layer supplies intelligence. The middle layer supplies an execution environment and feedback. The top layer packages tools around business outcomes. An organization can adopt one layer without buying into all three: for example, GLM-5.3 can sit behind a third-party coding agent through a compatible API, while ZCode can be used as the opinionated first-party environment.</p>
<p>This is the first useful architecture decision:</p>
<table>
<thead>
<tr>
<th>If you need</th>
<th>Start with</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td>A model endpoint inside an existing agent</td>
<td>GLM-5.3 API / Coding Plan</td>
<td>Lowest workflow switching cost</td>
</tr>
<tr>
<td>Long-running repository work with visible state</td>
<td>ZCode</td>
<td>Goal, files, terminal, browser, Git, and review stay together</td>
</tr>
<tr>
<td>Repeatable document, research, browser, or IM work</td>
<td>AutoClaw</td>
<td>The abstraction is a work outcome, not a code patch</td>
</tr>
<tr>
<td>Self-hosting or model-level research</td>
<td>Released GLM weights</td>
<td>You own serving, isolation, observability, and tuning</td>
</tr>
</tbody></table>
<h2>GLM-5.3: a post-training story, not a bigger-base story</h2>
<p>GLM-5.3 is interesting because Z.ai says it uses the same base model as GLM-5.2; the gains come from scaled post-training. The <a href="https://z.ai/blog/glm-5.3">official launch report</a> describes a stack inherited from GLM-5.2: IndexShare for long-context processing, SAO with compaction for long-horizon reinforcement learning, and the open-source <code>slime</code> infrastructure for asynchronous RL.</p>
<p>The conceptual shift is more important than the component names. Once a model can complete short coding exercises, the training bottleneck becomes the environment:</p>
<ul>
<li><p>Can the task actually be executed?</p>
</li>
<li><p>Is it solvable without hidden human knowledge?</p>
</li>
<li><p>Can success be checked without trusting the model's own explanation?</p>
</li>
<li><p>Does the task contain realistic state, dependencies, and failure modes?</p>
</li>
</ul>
<p>Z.ai describes a pipeline in which a research agent synthesizes work-like environments, a judge agent checks solvability, and generated verifiers are tested against oracle, no-op, and unsolved states. Reliable binary rewards can then train end-to-end behavior. That is a useful blueprint beyond this particular model: <strong>agent quality improves when done is machine-checkable</strong>.</p>
<p>The public numbers are substantial. In Z.ai's reported comparison, GLM-5.3 moves from 4.6 to 28.3 over GLM-5.2 on Terminal-Bench 3.0, from 46.2 to 66.9 on DeepSWE v1.1, and from 77.2 to 84.5 on CyberGym. Its private Z.ai Code Bench reports 34.5% task completion at roughly 75K output tokens per task at Max effort, versus 23.4% and 96K for GLM-5.2. These are vendor-reported results, not service-level guarantees. Treat them as hypotheses for your own evaluation, not as a procurement verdict.</p>
<h3>The API behavior that can break a migration</h3>
<p>GLM-5.3 always reasons. According to the <a href="https://z.ai/blog/glm-5.3">model launch documentation</a>, <code>thinking.type</code> must be <code>enabled</code>; disabling it is no longer accepted. Instead, control the budget with <code>reasoning_effort</code>, whose supported values are <code>low</code>, <code>high</code>, and <code>max</code>.</p>
<pre><code class="language-json">{
  "model": "glm-5.3",
  "thinking": { "type": "enabled" },
  "reasoning_effort": "max"
}
</code></pre>
<p>If an existing integration sends <code>"thinking": {"type": "disabled"}</code>, migrate in two steps:</p>
<ol>
<li><p>Keep the old model ID, switch thinking to <code>enabled</code>, and set effort to <code>low</code>.</p>
</li>
<li><p>Confirm the request path and response parser, then switch the model ID to <code>glm-5.3</code>.</p>
</li>
</ol>
<p>That sequence separates a schema failure from a model-behavior change.</p>
<p>For production, do not hard-code <code>max</code> everywhere. A reasonable policy is:</p>
<pre><code class="language-python">def reasoning_effort(task):
    if task in {"rename", "format", "small_test_fix"}:
        return "low"
    if task in {"feature", "debug", "review"}:
        return "high"
    return "max"  # architecture, migration, security investigation
</code></pre>
<p>The exact mapping should come from telemetry. Track success rate, retries, wall-clock latency, generated tokens, and human review time by task class. A cheaper first attempt is not cheaper if it creates two failed loops and a manual rescue.</p>
<h3>Context length is capacity, not memory quality</h3>
<p>GLM-5.3 exposes a 1,048,576-token context window and up to 128K output tokens. That capacity is valuable for large repositories and long agent traces, but it fits does not mean the model will use every token equally well.</p>
<p>An effective harness should still:</p>
<ul>
<li><p>search before loading files;</p>
</li>
<li><p>keep dependency and symbol summaries;</p>
</li>
<li><p>compact old tool output;</p>
</li>
<li><p>preserve decisions, test results, and failure evidence;</p>
</li>
<li><p>reload the authoritative source before editing it;</p>
</li>
<li><p>keep generated artifacts out of the context unless they are relevant.</p>
</li>
</ul>
<p>Think of a million-token window as a large address space, not a substitute for indexing and state management.</p>
<h2>ZCode: where model capability becomes engineering work</h2>
<p>ZCode calls itself an Agentic Development Environment. The useful difference from a chat panel is continuity: files, terminal results, browser state, execution mode, and Git changes remain part of the task. Its <a href="https://zcode.z.ai/en/docs/goal">Goal Mode documentation</a> says the agent checks the objective after each round and continues if it has not been met.</p>
<p>That makes the quality of the goal critical. Compare these two prompts:</p>
<pre><code class="language-text">Refactor checkout.
</code></pre>
<pre><code class="language-text">/goal Refactor checkout to isolate payment-provider logic behind an adapter.
Work only on feature/checkout-adapter. Preserve the public API.
Done means: unit and integration tests pass; no new TypeScript errors;
the Stripe and mock providers both complete the happy path; and the browser
checkout smoke test is captured with no console errors.
Do not modify migrations or production credentials.
</code></pre>
<p>The second prompt provides a branch boundary, invariants, executable checks, and explicit exclusions. It turns a vague intention into a verifier specification.</p>
<h3>A durable long-horizon loop</h3>
<p>For any agentic development environment, I want the same loop:</p>
<pre><code class="language-text">inspect  propose  change  test  observe  compare with goal  repeat
</code></pre>
<p>ZCode combines terminal and Git operations with a browser that the agent can drive. The <a href="https://zcode.z.ai/en/docs/browser-use">browser automation guide</a> documents navigation, form filling, screenshots, console-aware checks, and fixed viewport testing. This closes an important gap: frontend work should be validated against the rendered interface, not merely against source code and a green compiler.</p>
<p>A good browser acceptance test is concrete:</p>
<pre><code class="language-text">Open http://localhost:5173/checkout at 390844.
Buy the test product with the mock payment provider.
Verify the success page shows one order ID, the cart is empty,
and the console contains no errors. Save a screenshot as evidence.
Do not submit against any non-local environment.
</code></pre>
<p>Notice that permissions and environment boundaries are part of the test. Click through checkout is unsafe if the target URL is ambiguous.</p>
<h3>Use permissions as architecture</h3>
<p>ZCode's <a href="https://zcode.z.ai/en/docs/safety-confirm">safety documentation</a> separates the objective from the execution mode. That is the correct abstraction: <strong>what counts as done</strong> and <strong>what the agent may do without asking</strong> are independent controls.</p>
<p>I would use three practical zones:</p>
<ul>
<li><p><strong>Read zone:</strong> repository inspection, logs, documentation, and local browser checks.</p>
</li>
<li><p><strong>Reversible write zone:</strong> a feature branch, generated files, local tests, and disposable environments.</p>
</li>
<li><p><strong>Approval zone:</strong> credentials, production data, deployments, external messages, purchases, destructive commands, and security-sensitive disclosure.</p>
</li>
</ul>
<p>An agent that asks for approval on every file read is unusable. An agent that can deploy or send messages because the user said finish it is unsafe. The boundary should be encoded in the environment, not left as prose alone.</p>
<h3>Automate the boring checksbut keep the machine awake</h3>
<p>ZCode supports scheduled and idle-time work. The <a href="https://zcode.z.ai/en/docs/automations">automation documentation</a> notes that scheduled tasks run locally, require the computer to be awake with the app running, and are limited to 20 task definitions. That operational detail is more important than it looks: a local scheduler is not a cloud CI service.</p>
<p>Good candidates include nightly dependency-risk summaries, weekly release-note drafts, and queued test stabilization. Production gates should still live in CI, where execution and logs are controlled independently of a developer laptop.</p>
<p>Remote Control and Bot Channel are steering surfaces, not remote runtimes. The <a href="https://zcode.z.ai/en/docs/bot-channel">Bot Channel guide</a> describes WeChat and Feishu integration, while <a href="https://zcode.z.ai/en/docs/remote-control">Remote Control</a> forwards instructions to the already-connected desktop workspace. This distinction matters for security reviews: code still executes on the workstation; the phone or chat client is an entry point.</p>
<h2>AutoClaw: applying the agent loop beyond code</h2>
<p>AutoClaw moves the unit of work from produce a patch to produce a business artifact or completed workflow. Its <a href="https://autoclaw.z.ai/">official product page</a> describes a local desktop agent with more than 50 built-in skills spanning office documents, data, web, content, and automation, plus integrations such as WhatsApp, Telegram, Discord, and Lark.</p>
<p>The most valuable workflows are not one-shot prompts. They have a stable input, a repeatable procedure, evidence, and a human decision point. For example:</p>
<pre><code class="language-text">Every weekday, compare the public prices of these 12 products.
Record URL, observed price, promotion text, timestamp, and screenshot.
Flag changes over 5% and missing products. Produce a CSV and a short summary.
Do not log in, bypass access controls, or publish anything.
Send the draft to the review channel; a human decides any response.
</code></pre>
<p>That is much safer and more useful than monitor competitors. The artifact schema makes results comparable; screenshots make claims auditable; exclusions bound behavior; the human remains responsible for action.</p>
<p>For private files, runs locally is not the same as no data leaves the machine. AutoClaw states that model calls send the task description and required context. Before using sensitive data, determine exactly which files or excerpts are transmitted, where inference occurs, how logs are retained, and whether team policy permits it.</p>
<h2>Coding Plan and endpoint hygiene</h2>
<p>The GLM Coding Plan is a subscription layer shared by supported coding tools. The <a href="https://docs.z.ai/devpack/overview">official overview</a> currently lists Lite at 10,000 weekly credits, Pro at 60,000, and Max at 140,000, with both a rolling five-hour limit and a weekly limit. It also documents a 50% credit rate during off-peak hours and bundled MCP access. Price starts at $18 per month; verify the live <a href="https://z.ai/subscribe">subscription page</a> for the actual checkout price and term.</p>
<p>Endpoint mistakes can silently change billing. The <a href="https://docs.z.ai/api-reference/introduction">API introduction</a> distinguishes the Coding Plan endpoint from the general pay-as-you-go endpoint:</p>
<pre><code class="language-text">Coding Plan / OpenAI-compatible:
https://api.z.ai/api/coding/paas/v4

General API / pay-as-you-go:
https://api.z.ai/api/paas/v4

Anthropic Messages for supported coding tools:
https://api.z.ai/api/anthropic
</code></pre>
<p>The <a href="https://docs.z.ai/devpack/tool/others">tool integration guide</a> explicitly warns that the wrong endpoint will not use the Coding Plan quota. Put the base URL in one reviewed configuration source, print the selected host at startup without secrets, and alert on unexpected billing-project activity.</p>
<h2>A two-week engineering evaluation</h2>
<p>Do not evaluate an agent by asking it to build a toy app once. Use a task suite sampled from your real backlog.</p>
<h3>Week 1: establish baselines</h3>
<p>Select 2030 tasks across four buckets:</p>
<ul>
<li><p>small deterministic edits;</p>
</li>
<li><p>repository-scale debugging;</p>
</li>
<li><p>feature work with browser verification;</p>
</li>
<li><p>long-horizon refactors or migrations.</p>
</li>
</ul>
<p>For each task, record human-only baseline time, agent wall time, human attention time, retries, token or credit use, tests, review findings, and whether the patch was accepted. Freeze the repository revision and test fixtures so comparisons remain meaningful.</p>
<h3>Week 2: tune the system, not just the prompt</h3>
<p>Change one variable at a time: reasoning effort, goal specification, context retrieval, permission mode, or harness. Run the same task categories again. The most useful metrics are:</p>
<pre><code class="language-text">verified_success_rate = accepted_tasks / attempted_tasks
attention_saved       = baseline_human_minutes - review_and_rescue_minutes
cost_per_accept        = total_model_cost / accepted_tasks
unsafe_action_rate     = policy_violations / attempted_tasks
</code></pre>
<p>Also track false completion: the agent says done, but the acceptance checks fail. That is often more revealing than a benchmark score.</p>
<p>For security work, keep an isolated lab, use intentionally vulnerable or explicitly authorized targets, log tool activity, and require expert review. GLM-5.3's reported cyber capability makes boundary design morenot lessimportant.</p>
<h2>How I would choose</h2>
<p>Choose <strong>GLM-5.3 behind your existing agent</strong> when switching cost and price experimentation matter more than a first-party UI. Choose <strong>ZCode</strong> when long-running repository work, visible tool state, browser verification, and local steering are the main problem. Choose <strong>AutoClaw</strong> when the output is a report, spreadsheet, browser workflow, or team-chat deliverable rather than a mergeable patch.</p>
<p>And choose none of them yet if you cannot define success, isolate permissions, or observe what the agent did. Agent adoption is not primarily a model-selection exercise. It is the engineering of verifiers, boundaries, and feedback loops.</p>
<p>The strongest idea in the Z.ai stack is therefore not a particular benchmark number. It is the alignment of three layers: a model trained on long-horizon environments, a development harness that preserves execution context, and work agents that package repeatable outcomes. Used carefully, that alignment can reduce handoffs and supervision. Used casually, it can simply automate ambiguity faster.</p>
<p>Start with one bounded workflow. Make done executable. Measure accepted outcomes. Expand only when the evidence says the system deserves a larger blast radius.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-08-24-0212</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-08-24-0212</guid><category><![CDATA[ai agents]]></category><category><![CDATA[llm]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Factory AI in 2026: From Specialized Droids to an Agent-Native Engineering System]]></title><description><![CDATA[<p>In November 2025, I published <a href="https://daisuke.masuda.tokyo/article-2025-11-03-0139">Factory AI: A Comprehensive Look at Agent-Native Software Development</a>. That article described Factory through four specialized agentsCode, Reliability, Knowledge, and Tutorial Droidsand concepts such as HyperCode and ByteRank. It captured an interesting moment, but the product has moved quickly.</p>
<p>This is the 2026 update.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/factory-ai-the-complete-guide-2026">https://speakerdeck.com/x5gtrn/factory-ai-the-complete-guide-2026</a></p>

<p>The most important change is not a longer feature list. Factory now makes more sense as an <strong>engineering execution system</strong>: one Droid runtime that can work interactively, launch parallel Missions, delegate to custom subagents, reuse team procedures as Skills, and run headlessly in CI. Around that runtime sits an increasingly serious control plane for permissions, sandboxing, governance, observability, and measuring whether a repository is actually ready for autonomous work.</p>
<p>That shift also changes the right question. Instead of asking, How good is Factory at generating code?, ask:</p>
<blockquote>
<p>Can my repository turn an explicit engineering intent into a small, reviewable, verified changewith enough evidence that a human can safely approve it?</p>
</blockquote>
<p>This guide explains the current architecture, shows concrete workflows, and separates useful engineering practice from agent hype.</p>
<h2>The 2025 mental model vs. the 2026 product</h2>
<p>The earlier article organized Factory around four named specialists. That was easy to understand, but the current documentation emphasizes a more composable system.</p>
<table>
<thead>
<tr>
<th>2025 framing</th>
<th>2026 framing</th>
<th>Why it matters</th>
</tr>
</thead>
<tbody><tr>
<td>Four fixed specialist Droids</td>
<td>A coordinator, five built-in roles, plus Custom Droids</td>
<td>Factory adds Review and separates orchestration from execution; teams can still define their own specialists</td>
</tr>
<tr>
<td>Interactive assistance</td>
<td>Interactive CLI, app, IDE, and headless <code>droid exec</code></td>
<td>The same runtime can move from pairing to automation</td>
</tr>
<tr>
<td>Agent capability as the headline</td>
<td>Repository readiness and verifiable workflows</td>
<td>Reliability depends as much on the environment as on the model</td>
</tr>
<tr>
<td>One agent completing a task</td>
<td>Missions coordinating parallel agents</td>
<td>Larger objectives can be decomposed without sharing one mutable workspace blindly</td>
</tr>
<tr>
<td>Prompting as configuration</td>
<td><code>AGENTS.md</code>, Rules, Memories, Skills, hooks, and MCP</td>
<td>Operating knowledge becomes versionable infrastructure</td>
</tr>
<tr>
<td>Broad security claims</td>
<td>Concrete command lists, sandboxing, hooks, and Droid Shield</td>
<td>Teams can enforce boundaries independently of model behavior</td>
</tr>
</tbody></table>
<p>The 2026 deck depicts a coordinator that decomposes work and delegates to five roles: Code, Review, Test, Docs, and Knowledge Droids. The old categories have not become useless; they have become part of a broader orchestration model. In the product, teams can also encode their own specialists as Custom Droids and their repeatable procedures as Skills.</p>
<h2>What agent-native should mean to an engineer</h2>
<p>Autocomplete predicts the next tokens. Chat answers questions. An engineering agent participates in a feedback loop:</p>
<ol>
<li><p>inspect the repository and its constraints;</p>
</li>
<li><p>propose a plan;</p>
</li>
<li><p>use tools to change the environment;</p>
</li>
<li><p>run tests, linters, and other checks;</p>
</li>
<li><p>interpret failures and revise;</p>
</li>
<li><p>produce a diff and evidence for review.</p>
</li>
</ol>
<p>Factory's current <a href="https://docs.factory.ai/droid-cli/overview">Droid CLI overview</a> describes a runtime with project context, approvals, MCP tools, Missions, custom Droids, Skills, and headless execution. The agent-native part is therefore not a special model. It is the harness surrounding whichever model you select: context acquisition, tool execution, state, policy, and verification.</p>
<p>This distinction matters. A stronger model can improve planning or code generation, but it cannot compensate for a repository with no deterministic build, slow tests, undocumented conventions, or unrestricted credentials. Agent performance is a systems property.</p>
<h2>The current Factory stack</h2>
<h3>1. Droid CLI: the interactive control surface</h3>
<p>Installation remains intentionally simple:</p>
<pre><code class="language-bash">curl -fsSL https://app.factory.ai/cli | sh
cd /path/to/repository
droid
</code></pre>
<p>From there, Droid works next to Git, tests, and the editor. Factory's <a href="https://docs.factory.ai/reference/cli-reference">CLI reference</a> exposes interactive operations for model selection, review, sessions, MCP servers, hooks, Skills, Custom Droids, Missions, and readiness reports. Git worktree support is particularly useful: separate tasks can operate on separate branches and directories instead of racing over the same files.</p>
<p>For non-trivial changes, begin in Spec Mode. Ask the agent to explore before editing, identify uncertainty, and write acceptance criteria. A good implementation request looks like an issue a senior engineer would be comfortable handing to a new teammate:</p>
<pre><code class="language-text">Add idempotency to POST /payments.

Scope:
- API and persistence layers only; do not change the public response schema.
- Use the Idempotency-Key header and retain results for 24 hours.
- Concurrent requests with the same key must create at most one charge.

Acceptance criteria:
- Unit tests cover replay, conflicting payloads, expiry, and concurrency.
- Existing integration tests pass.
- Add a short ADR explaining the storage and locking decision.

Before editing, inspect the payment flow and propose a plan with risks.
</code></pre>
<p>Notice what is absent: use clean code, be production-ready, or do it perfectly. Those phrases do not give the agent a testable target.</p>
<h3>2. <code>AGENTS.md</code>, Rules, and Memories: context as infrastructure</h3>
<p>Repeatedly explaining the same build commands is both expensive and unreliable. Factory supports repository instructions in <code>AGENTS.md</code>, persistent Rules, and Memories. The <a href="https://docs.factory.ai/guides/power-user/setup-checklist">power-user setup checklist</a> documents project and personal locations for these resources.</p>
<p>A minimal <code>AGENTS.md</code> might be:</p>
<pre><code class="language-markdown"># Repository guide

## Architecture
- `apps/api`: Fastify HTTP API
- `packages/domain`: framework-free business logic
- `packages/db`: migrations and query layer

## Verification
- Format: `pnpm format:check`
- Types: `pnpm typecheck`
- Unit tests: `pnpm test`
- API integration tests: `pnpm test:integration`

## Constraints
- Never edit generated clients under `packages/sdk/generated`.
- Database changes require a backward-compatible migration.
- Do not merge or push; leave a reviewed local commit.
</code></pre>
<p>Treat this file like code. Keep it short, review changes, and prefer executable commands over prose. A stale instruction file is worse than no instruction file because it produces confident failures.</p>
<h3>3. Skills: versioned engineering procedures</h3>
<p>A Skill turns a repeatable procedure into a reusable capability. Factory's <a href="https://docs.factory.ai/cli/configuration/skills">Skills guide</a> recommends explicit scope, verification, proof artifacts, safe failure behavior, and composability.</p>
<p>Good Skill candidates include:</p>
<ul>
<li><p>adding an API endpoint using your service template;</p>
</li>
<li><p>upgrading a dependency across a monorepo;</p>
</li>
<li><p>producing an incident evidence bundle;</p>
</li>
<li><p>validating a database migration;</p>
</li>
<li><p>generating a release note from a semantic diff.</p>
</li>
</ul>
<p>The best Skills are not elaborate prompts. They are compact runbooks with preconditions, boundaries, commands, expected artifacts, and stop conditions. For production-adjacent work, require a pull request and forbid autonomous merging.</p>
<h3>4. Custom Droids: organization-specific specialists</h3>
<p>Custom Droids let you encode roles that match the real ownership map of your system: <code>payments-reviewer</code>, <code>terraform-auditor</code>, <code>mobile-release-engineer</code>, or <code>postgres-migration-reviewer</code>. This is more useful than a universal testing agent because a specialist can carry the relevant tools, instructions, and domain constraints.</p>
<p>A useful rule is: create a Custom Droid when a task needs a distinct role or tool boundary; create a Skill when it needs a repeatable procedure. The two compose naturallya release Droid can invoke release-validation Skills.</p>
<h3>5. Missions: parallel work with explicit decomposition</h3>
<p>Missions coordinate multiple agents for objectives that can be divided into independent workstreams. In practice, parallelism is valuable only when ownership is clear.</p>
<p>For a framework migration, reasonable branches might be:</p>
<ul>
<li><p>inventory deprecated APIs;</p>
</li>
<li><p>migrate the core library;</p>
</li>
<li><p>update application integrations;</p>
</li>
<li><p>expand regression tests;</p>
</li>
<li><p>update developer documentation.</p>
</li>
</ul>
<p>Do not create five agents to edit the same central module. The coordination cost and merge risk will dominate. Prefer bounded tasks, separate worktrees, declared dependencies, and a final integration phase. Parallel agents amplify both good decomposition and bad decomposition.</p>
<h3>6. Droid Computers: persistent execution environments</h3>
<p>The slide deck gives Droid Computers unusual prominence, and rightly so. Autonomous work lasting hours or days does not fit an ephemeral chat sandbox that must reinstall dependencies and reconstruct state on every run.</p>
<p><a href="https://docs.factory.ai/cli/features/droid-computers">Droid Computers</a> are long-lived environments that retain packages, files, services, credentials, and configuration across sessions. Factory offers both managed computers and Bring Your Own Machine (BYOM). Factory provisions a managed instance; BYOM registers infrastructure you already control, such as a workstation, VPS, or on-premises server.</p>
<p>Persistence removes setup cost, but it also changes the threat model. State can drift, credentials can outlive a task, and a compromised dependency can persist. Treat a Droid Computer like a developer workstation or CI runner: patch it, isolate it, monitor it, rotate credentials, constrain network access, and periodically rebuild it from a known configuration. Persistent should not mean pet server nobody can reproduce.</p>
<h3>7. Factory Router: model selection becomes infrastructure</h3>
<p>The 2026 deck introduces Factory Router as a cost-optimization layer. Instead of asking every engineer to choose among fast, affordable, and frontier models, the router classifies a session and selects an appropriate model, with escalation or provider failover when needed.</p>
<p>Factory's <a href="https://factory.ai/product/router">Router product page</a> reports aggregate production savings and says the router is available in CLI and Desktop, including Mission workers. Its <a href="https://factory.ai/news/factory-router">June 2026 announcement</a> also publishes comparisons against an Opus baseline. Those numbers are vendor-reported and workload-dependent, so they should be a hypothesis for your own evaluationnot a procurement guarantee.</p>
<p>The architectural idea is sound: documentation edits, repository search, and mechanical refactors should not automatically consume the same inference budget as an ambiguous cross-service design. But routing needs policy. Authentication and payments code may deserve a frontier model even for a small diff; sensitive repositories may restrict eligible providers; and fallback behavior must preserve data-residency requirements.</p>
<h3>8. Factory Analytics: measure outcomes, not activity</h3>
<p>Factory Analytics closes the economic loop. The official <a href="https://docs.factory.ai/reference/analytics-api">Analytics API</a> exposes token consumption, tool use, user activity, productivity signals, and per-user metrics; enterprise deployments can also use <a href="https://docs.factory.ai/enterprise/usage-cost-and-analytics">OpenTelemetry-native usage and cost telemetry</a>.</p>
<p>Token savings are useful operational data, but more tool calls and more generated files are not productivity. Join Factory telemetry with delivery metrics such as accepted PR lead time, change failure rate, review time, escaped defects, and rollback rate. The unit of value is a verified change that the team wantednot an active session.</p>
<h3>9. Droid Exec: from conversation to automation</h3>
<p><a href="https://docs.factory.ai/cli/droid-exec/overview"><code>droid exec</code></a> is the bridge from interactive work to CI/CD. It runs a one-shot task, exits with a success or failure status, and supports human-readable or structured output. Importantly, it is read-only by default; mutations require an explicit autonomy level.</p>
<p>For read-only PR analysis:</p>
<pre><code class="language-bash">droid exec \
  --output-format json \
  --cwd "$CHECKOUT" \
  "Review the diff against origin/main. Return JSON with severity, file, line, evidence, and suggested test. Do not edit files."
</code></pre>
<p>For a controlled documentation workflow:</p>
<pre><code class="language-bash">droid exec \
  --auto low \
  --cwd "$CHECKOUT" \
  "Update only docs/ for the API changes in the current diff. Run the docs link checker and write a summary to artifacts/docs-update.md."
</code></pre>
<p>The Factory documentation explicitly warns that <code>--skip-permissions-unsafe</code> bypasses all checks and belongs only in disposable, isolated environments. In normal CI, prefer the lowest autonomy that works, constrain the working directory, restrict tools, and ask for artifacts your pipeline can validate.</p>
<p>For deeper integrations, Droid Exec also provides streaming JSON-RPC and official TypeScript and Python SDK paths. That makes the runtime usable behind an internal portal or policy layer without scraping terminal text.</p>
<h2>A practical end-to-end workflow</h2>
<p>Suppose you need to upgrade an authentication library with a breaking API change.</p>
<h3>Phase 1: establish a baseline</h3>
<p>Before delegating anything, make the repository reproducible:</p>
<pre><code class="language-bash">pnpm install --frozen-lockfile
pnpm typecheck
pnpm test
</code></pre>
<p>Record failures that already exist. Otherwise the agent may fix unrelated problems or claim responsibility for a pre-existing failure.</p>
<h3>Phase 2: explore in Spec Mode</h3>
<p>Ask Droid to locate imports, configuration, wrappers, tests, and security-sensitive paths. Require a migration plan that distinguishes mechanical edits from semantic changes. Make it identify what cannot be verified locally.</p>
<h3>Phase 3: implement a narrow slice</h3>
<p>Start with one package or service. Do not begin with the entire monorepo. Require the smallest diff that proves the migration pattern, including tests. Review the pattern before scaling it.</p>
<h3>Phase 4: scale safely</h3>
<p>Once the pattern is accepted, encode it as a Skill or delegate independent packages through a Mission. Use worktrees so each branch has an isolated filesystem. Keep a deterministic integration order.</p>
<h3>Phase 5: demand evidence</h3>
<p>The final response should not merely say all tests pass. Require:</p>
<ul>
<li><p>exact commands and exit status;</p>
</li>
<li><p>changed-file summary;</p>
</li>
<li><p>test additions and what behavior they cover;</p>
</li>
<li><p>unresolved risks or skipped checks;</p>
</li>
<li><p>a diff or pull request for human review.</p>
</li>
</ul>
<p>The agent's prose is not evidence. Logs, tests, generated reports, and reviewable diffs are evidence.</p>
<h2>Agent Readiness: the underappreciated feature</h2>
<p>Factory's <a href="https://docs.factory.ai/web/agent-readiness/overview">Agent Readiness Model</a> evaluates repositories across nine technical pillars and gates progression: a repository must pass 80% of one level's criteria to unlock the next. It can be invoked with <code>/readiness-report</code>, viewed in a dashboard, or accessed programmatically.</p>
<p>Even if you never accept the scoring model as objective truth, the framing is correct. Agent throughput is constrained by machine-readable feedback:</p>
<ul>
<li><p>Can a fresh checkout build deterministically?</p>
</li>
<li><p>Are formatting, types, tests, and security checks fast enough to run repeatedly?</p>
</li>
<li><p>Are module boundaries and ownership visible?</p>
</li>
<li><p>Are secrets and production systems isolated?</p>
</li>
<li><p>Can success be evaluated without subjective interpretation?</p>
</li>
</ul>
<p>This leads to a useful inversion: improving your repository for agents often improves it for humans. Faster tests, clearer ownership, stable commands, and documented architecture reduce onboarding and review costs regardless of who writes the patch.</p>
<h2>Security: treat the model as untrusted</h2>
<p>Factory's current <a href="https://docs.factory.ai/enterprise/llm-safety-and-agent-controls">Agent Safety &amp; Controls documentation</a> says this directly: build on deterministic controls rather than trusting model behavior.</p>
<p>The available layers include:</p>
<ul>
<li><p>command allow, deny, and blocklists;</p>
</li>
<li><p>programmable hooks around lifecycle events;</p>
</li>
<li><p>filesystem and network sandboxing;</p>
</li>
<li><p>network egress restrictions;</p>
</li>
<li><p>Droid Shield scanning around Git commit and push;</p>
</li>
<li><p>managed organization and project policies.</p>
</li>
</ul>
<p>The distinction between a denylist and a blocklist is important. A denied command can still run after explicit approval. A blocked command has no approval path, including under high autonomy. Use a blocklist for actions the organization has decided must never occur.</p>
<p>A sensible production policy is:</p>
<ol>
<li><p>no long-lived production credentials in the agent environment;</p>
</li>
<li><p>no direct merge or deployment authority;</p>
</li>
<li><p>write access limited to the task's repository or worktree;</p>
</li>
<li><p>network egress limited to required package registries and APIs;</p>
</li>
<li><p>every change goes through normal CI and code review;</p>
</li>
<li><p>tool calls and policy decisions are logged;</p>
</li>
<li><p>prompts and retrieved content are treated as potentially hostile input.</p>
</li>
</ol>
<p>MCP expands capability and attacks surface at the same time. An MCP server should be reviewed like any dependency with access to internal systems: authenticate it, minimize its scopes, pin and audit it where possible, and decide whether it belongs at user, project, or organization level.</p>
<h3>Security Review is a workflow, not a magic shield</h3>
<p>The deck highlights automated security review on every pull request. Factory's current <a href="https://docs.factory.ai/enterprise/security-review">Security Review documentation</a> describes a two-pass process: generate candidate issues, then validate reachability, exploitability, and existing controls before reporting. Its methodology combines STRIDE, OWASP Top 10, the OWASP Top 10 for LLM applications, supply-chain checks, and an optional repository threat model in <code>.factory/threat-model.md</code>.</p>
<p>You can invoke <code>/security-review</code> locally or enable a dedicated review in Droid Action. A full-repository scan writes a report on a separate branch and opens a PR. That is a useful review layer, especially for tracing changed data flows, but it is not a substitute for SAST, dependency scanning, secret detection, fuzzing, penetration testing, or a security engineer. Treat agent findings as hypotheses with evidence and track false positives and missed vulnerabilities over time.</p>
<h2>Model choice and benchmarks</h2>
<p>The 2025 article cited SWE-bench and TerminalBench numbers as if they described Factory as a stable unit. That interpretation is now less useful. Factory is a multi-model harness, and results depend on model, reasoning budget, tools, repository context, and the evaluation scaffold.</p>
<p>Factory now publishes a <a href="https://docs.factory.ai/benchmarks/review-benchmark">code review benchmark</a> based on 50 pull requests from five large open-source projects and a manually curated set of validated bugs. That is useful evidence for the narrower question which model is cost-effective for bug-finding in this harness? It is not proof that the same model will excel at your migrations, UI work, or incident response.</p>
<p>Build a small internal evaluation instead:</p>
<table>
<thead>
<tr>
<th>Metric</th>
<th>Example definition</th>
</tr>
</thead>
<tbody><tr>
<td>Task success</td>
<td>Acceptance tests pass without relaxing requirements</td>
</tr>
<tr>
<td>Review burden</td>
<td>Human minutes from first diff to approval</td>
</tr>
<tr>
<td>Rework</td>
<td>Number of agent revisions after review</td>
</tr>
<tr>
<td>Escaped defects</td>
<td>Regressions attributable to accepted agent changes</td>
</tr>
<tr>
<td>Cost</td>
<td>Model plus infrastructure cost per accepted task</td>
</tr>
<tr>
<td>Lead time</td>
<td>Time from assigned tasks to reviewable evidence</td>
</tr>
</tbody></table>
<p>Use representative tasks, keep a fixed baseline, and record failuresnot just wins. Optimize for accepted engineering outcomes per dollar, not tokens generated or lines changed.</p>
<h2>Pricing and rollout</h2>
<p>The old article described a free BYOK tier plus Pro and Max. Current <a href="https://docs.factory.ai/pricing">Factory pricing</a> lists individual Pro, Plus, and Max plans, along with Teams and Enterprise offerings, rolling rate limits, optional Extra Usage, and a Droid Core pool. BYOK is described as an allowance within plans rather than an unlimited free tier. Pricing changes quickly, so check the official page before budgeting.</p>
<p>A realistic rollout is deliberately boring:</p>
<ol>
<li><p><strong>Week 1: read-only pilot.</strong> Repository Q&amp;A, change-impact analysis, and PR review.</p>
</li>
<li><p><strong>Weeks 23: low-risk edits.</strong> Tests, docs, and mechanical refactors on isolated branches.</p>
</li>
<li><p><strong>Weeks 46: codify success.</strong> Add <code>AGENTS.md</code>, Skills, hooks, metrics, and a small internal evaluation set.</p>
</li>
<li><p><strong>After evidence: automate.</strong> Move stable workflows to Droid Exec; use Missions only where parallel decomposition is natural.</p>
</li>
</ol>
<p>Choose one team and two or three repeatable tasks. Compare against a baseline. If review time rises or defects increase, stop and improve the environment before increasing autonomy.</p>
<h2>Where Factory fitsand where it does not</h2>
<p>Factory is compelling when you want the same agent runtime across terminal, IDE, scripts, CI, and team workflows; when you value model choice; and when you are willing to encode engineering knowledge and controls around it.</p>
<p>It may be excessive for a small repository that only needs autocomplete and occasional chat. It is also a poor fit for teams that cannot make builds reproducible, expose verification commands, or keep humans accountable for production changes. More autonomy does not repair weak engineering systems; it makes their weaknesses operate faster.</p>
<p>The defensible advantage is not Droid writes more code. It is the ability to turn team knowledge into versioned, executable operating procedures and run them through a governed agent harness.</p>
<h2>Factory does not have to replace your other coding agents</h2>
<p>Two slides show Factory working alongside Claude Code, Cursor, and Sentry. That is a more realistic architecture than declaring one universal winner.</p>
<ul>
<li><p>Use an editor-native tool for rapid, synchronous exploration and small local edits.</p>
</li>
<li><p>Hand a well-specified, long-running migration or multi-repository task to a Mission.</p>
</li>
<li><p>Use Factory's review and security workflows as an independent background check.</p>
</li>
<li><p>Connect operational systems through narrowly scoped MCP serversfor example, allowing an incident workflow to read a Sentry issue and repository context, then prepare a fix for review.</p>
</li>
</ul>
<p>The handoff contract matters more than the brand combination. Pass the ticket, acceptance criteria, relevant paths, current diff, and verification status. Avoid letting two agents concurrently mutate the same branch. For incident automation, keep the progression explicit: alert  evidence collection  candidate root cause  patch and tests  human approval  deployment through the normal pipeline.</p>
<p>This is where the software factory metaphor earns its keep. A factory is not one machine. It is a controlled production system with specialized stations, quality gates, feedback, maintenance, and accountable operators.</p>
<h2>Final take</h2>
<p>Factory AI in 2026 is materially different from the platform I described in November 2025. The earlier story was about four specialized Droids and impressive autonomous capabilities. The current story is more mature: a general Droid runtime, composable specialists and Skills, parallel Missions, headless execution, measurable repository readiness, and deterministic safety controls.</p>
<p>That evolution makes Factory more interestingbut also removes excuses for careless adoption.</p>
<p>Start with a well-scoped task. Give the agent executable context. Keep mutations narrow. Make verification automatic. Treat the model as untrusted. Require evidence. Measure accepted outcomes. Only then increase autonomy.</p>
<p>Agent-native engineering is not the removal of engineers from the loop. It is the redesign of the loop so human intent, machine execution, deterministic checks, and accountable review fit together.</p>
<h2>Further reading</h2>
<ul>
<li><p><a href="https://docs.factory.ai/droid-cli/overview">Factory Droid CLI overview</a></p>
</li>
<li><p><a href="https://docs.factory.ai/cli/droid-exec/overview">Droid Exec: headless automation</a></p>
</li>
<li><p><a href="https://docs.factory.ai/web/agent-readiness/overview">Factory Agent Readiness Model</a></p>
</li>
<li><p><a href="https://docs.factory.ai/cli/features/droid-computers">Droid Computers</a></p>
</li>
<li><p><a href="https://factory.ai/product/router">Factory Router</a></p>
</li>
<li><p><a href="https://docs.factory.ai/reference/analytics-api">Factory Analytics API</a></p>
</li>
<li><p><a href="https://docs.factory.ai/enterprise/llm-safety-and-agent-controls">Factory Agent Safety &amp; Controls</a></p>
</li>
<li><p><a href="https://docs.factory.ai/enterprise/security-review">Factory Security Review</a></p>
</li>
<li><p><a href="https://docs.factory.ai/cli/configuration/skills">Factory Skills guide</a></p>
</li>
<li><p><a href="https://docs.factory.ai/pricing">Factory plans and pricing</a></p>
</li>
<li><p><a href="https://daisuke.masuda.tokyo/article-2025-11-03-0139">The November 2025 version of this article</a></p>
</li>
<li><p><a href="https://speakerdeck.com/x5gtrn/factory-ai-the-complete-guide-to-agent-native-software-development">The original Factory AI slide deck on Speaker Deck</a></p>
</li>
</ul>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-08-11-1401</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-08-11-1401</guid><category><![CDATA[AI]]></category><category><![CDATA[software development]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[automation]]></category><category><![CDATA[Orchestration]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Apache Kafka: A Complete Engineer's Guide to Real-Time Data Streaming]]></title><description><![CDATA[<blockquote>
<p>"Kafka is the central nervous system of a modern data architecture. Once you've seen it at scale, you can't unsee it."  An engineer who has debugged a RabbitMQ cluster at 3 AM</p>
</blockquote>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/apache-kafka-a-complete-engineers-guide">https://speakerdeck.com/x5gtrn/apache-kafka-a-complete-engineers-guide</a></p>

<hr />
<h2>1. The Problem Kafka Was Built to Solve</h2>
<p>Let me paint you a picture. It's 2010. LinkedIn is growing explosively. Engineers are trying to pipe activity data  page views, clicks, job applications, connection events  into multiple downstream systems: Hadoop for batch analytics, a recommendation engine, a monitoring stack. Every team is building their own point-to-point integration. The result? A tangled web of pipelines, each with its own failure modes, each struggling to keep up with millions of events per second.</p>
<p>Traditional <a href="https://en.wikipedia.org/wiki/Relational_database">RDBMS</a> systems weren't designed for this. Message queues like ActiveMQ or RabbitMQ were better, but they traded high throughput for low latency or vice versa  rarely both. The architectural gap between <strong>"store-and-query"</strong> and <strong>"stream-and-react"</strong> was real and painful.</p>
<p>Four concrete challenges drove Kafka's creation:</p>
<ul>
<li><p><strong>Volume:</strong> Modern web services generate millions of events per second. A single microservices platform at a mid-size company can emit tens of thousands of events per minute.</p>
</li>
<li><p><strong>Throughput vs. Latency tension:</strong> Traditional message brokers excel at complex routing but buckle under high throughput. RDBMS are durable but add latency and don't scale horizontally for writes.</p>
</li>
<li><p><strong>Microservices coupling:</strong> When services talk directly to each other, you get a distributed monolith. Asynchronous, decoupled communication is the prerequisite for true microservices independence.</p>
</li>
<li><p><strong>The analytics gap:</strong> You want to log every event, aggregate them centrally, and feed real-time analytics dashboards  all simultaneously, from the same data source.</p>
</li>
</ul>
<p>Kafka was built to solve all of this with a single, elegant abstraction: <strong>a distributed, append-only, fault-tolerant commit log</strong>.</p>
<hr />
<h2>2. What Is Apache Kafka, Really?</h2>
<p><a href="https://kafka.apache.org/">Apache Kafka</a> is an open-source <strong>distributed event streaming platform</strong>, originally developed by engineers at <a href="https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying">LinkedIn in 2011</a> and subsequently donated to the <a href="https://www.apache.org/">Apache Software Foundation</a>. It is released under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>.</p>
<p>The official tagline  "distributed event streaming platform"  is precise but abstract. Here's a more grounded definition:</p>
<blockquote>
<p><strong>Kafka is a high-throughput, fault-tolerant, persistent message bus that allows producers to publish events and consumers to subscribe to them independently, at any time, at any speed.</strong></p>
</blockquote>
<p>Three properties distinguish it from conventional messaging systems:</p>
<table>
<thead>
<tr>
<th>Property</th>
<th>Kafka</th>
<th>Traditional MQ</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Message persistence</strong></td>
<td>Configurable (default 7 days, can be infinite)</td>
<td>Deleted after consumption</td>
</tr>
<tr>
<td><strong>Multiple consumers</strong></td>
<td>Any number can read the same message independently</td>
<td>Usually single consumer per message</td>
</tr>
<tr>
<td><strong>Throughput target</strong></td>
<td>Millions of messages/sec per cluster</td>
<td>Tens to hundreds of thousands/sec</td>
</tr>
</tbody></table>
<p>Kafka is now the backbone of companies like <a href="https://netflixtechblog.com/kafka-inside-keystone-pipeline-dd5aeabaf6bb">Netflix</a>, <a href="https://eng.uber.com/reliable-reprocessing/">Uber</a>, LinkedIn itself, Airbnb, PayPal, and thousands of others. It is not a niche tool  it is critical infrastructure for the modern internet.</p>
<hr />
<h2>3. The 5 Core Concepts You Must Understand</h2>
<p>Understanding Kafka's vocabulary is non-negotiable. These five terms appear in every Kafka conversation.</p>
<h3>1. Producer</h3>
<p>A <strong>Producer</strong> is any application that publishes (writes) messages to Kafka. It decides which Topic  and optionally which Partition  to send a message to.</p>
<p>Think of it as a <strong>newspaper publisher</strong> choosing which section of the paper to print a story in.</p>
<pre><code class="language-java">// Spring Boot Kafka Producer (Java)
@Service
public class OrderEventProducer {
    private final KafkaTemplate&lt;String, OrderEvent&gt; kafkaTemplate;

    public void publish(OrderEvent event) {
        kafkaTemplate.send("order-events", event.getOrderId(), event);
    }
}
</code></pre>
<h3>2. Consumer</h3>
<p>A <strong>Consumer</strong> is any application that subscribes to and reads messages from Kafka. The key insight: <strong>Consumers pull messages</strong>  Kafka never pushes. This means consumers control their own processing pace, making back-pressure handling natural.</p>
<p>Think of it as a <strong>newspaper subscriber</strong> who picks up the paper and reads at their own pace.</p>
<pre><code class="language-java">// Spring Boot Kafka Consumer (Java)
@KafkaListener(topics = "order-events", groupId = "inventory-service")
public void consume(OrderEvent event) {
    inventoryService.reserveStock(event);
}
</code></pre>
<h3>3. Topic</h3>
<p>A <strong>Topic</strong> is a named, logical category for messages. Producers send to a Topic; Consumers subscribe to a Topic. Topics are durable  they persist data to disk, not just in memory.</p>
<p>Analogy: the <strong>"Sports Section"</strong> of a newspaper. Everything sports-related goes there; sports readers subscribe to that section.</p>
<h3>4. Partition</h3>
<p>A <strong>Partition</strong> is the physical unit of a Topic. Each Topic is split into one or more Partitions, distributed across Brokers in the cluster. This is how Kafka achieves horizontal scalability  more Partitions means more parallelism.</p>
<p>Critical rule: <strong>message ordering is guaranteed within a Partition, but not across Partitions</strong>. Design your partition key accordingly. For example, if you need all events for a given user to be ordered, use <code>userId</code> as the partition key.</p>
<h3>5. Broker</h3>
<p>A <strong>Broker</strong> is a single Kafka server (node) in the cluster. It stores data for one or more Partitions and handles producer/consumer connections. A production cluster typically has 3 or more Brokers for fault tolerance.</p>
<p>Think of it as a <strong>distribution center</strong> that stores and forwards the right sections of the newspaper to the right subscribers.</p>
<blockquote>
<p><strong>Mental model summary:</strong> Producers write  Brokers store (in Topics/Partitions)  Consumers read by subscribing.</p>
</blockquote>
<hr />
<h2>4. Architecture Deep Dive  How Data Actually Flows</h2>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/69f82678-73ec-4f13-a7d4-58b4c47967af.jpg" alt="" style="display:block;margin:0 auto" />

<p>Kafka's architecture is elegantly layered. Let's trace a message from birth to consumption.</p>
<pre><code class="language-plaintext">Producer  Broker Cluster (Topic/Partitions)  Consumer Group
                    
            KRaft Controllers
          (Metadata Management)
</code></pre>
<h3>The Data Flow</h3>
<ol>
<li><p>A <strong>Producer</strong> serializes a message (key + value + optional headers) and sends it to a specific Topic.</p>
</li>
<li><p>The Producer's <strong>partitioner</strong> determines which Partition to route to. Default: round-robin (no key) or <code>murmur2(key) % numPartitions</code> (with key).</p>
</li>
<li><p>The <strong>Leader Broker</strong> for that Partition appends the message to its log and acknowledges the Producer (depending on <code>acks</code> config).</p>
</li>
<li><p><strong>Follower Brokers</strong> replicate the message asynchronously.</p>
</li>
<li><p><strong>Consumers</strong> in a Consumer Group poll for new messages, each Consumer owning a subset of Partitions.</p>
</li>
</ol>
<h3>Consumer Groups  The Scalability Multiplier</h3>
<p>Consumer Groups are one of Kafka's most powerful features. Within a group, each Partition is consumed by exactly one Consumer. This means:</p>
<ul>
<li><p>3 Partitions + 3 Consumers = each consumer handles 1 partition in parallel.</p>
</li>
<li><p>3 Partitions + 1 Consumer = that consumer handles all 3 partitions sequentially.</p>
</li>
<li><p>3 Partitions + 5 Consumers = 2 consumers sit idle (you can't have more active consumers than partitions in a group).</p>
</li>
</ul>
<p>But two <strong>different Consumer Groups</strong> can each read all messages from the same Topic independently  this is the "fan-out" pattern. The same <code>order-events</code> Topic can simultaneously feed an inventory service, a notification service, and an analytics pipeline, all at their own pace.</p>
<h3>KRaft  ZooKeeper Is Dead, Long Live KRaft</h3>
<p>Historically, Kafka relied on <a href="https://zookeeper.apache.org/">Apache ZooKeeper</a> for cluster metadata management (which broker is the leader, topic configurations, consumer group offsets). As of <strong>Kafka 3.3</strong>, <a href="https://kafka.apache.org/documentation/#kraft">KRaft (Kafka Raft)</a> became production-ready, replacing ZooKeeper entirely. As of Kafka 4.0 (2024), ZooKeeper mode was fully removed.</p>
<p>KRaft embeds a Raft consensus protocol directly into Kafka's controller quorum. Benefits:</p>
<ul>
<li><p>Eliminates operational complexity of maintaining a separate ZooKeeper ensemble.</p>
</li>
<li><p>Faster controller failover (sub-second vs. seconds).</p>
</li>
<li><p>Supports up to millions of partitions per cluster (vs. ZooKeeper's practical limit of ~200K).</p>
</li>
</ul>
<hr />
<h2>5. Partitions and Offsets  The Key to Scalability</h2>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/bb68882c-49bc-466e-9b1f-03bf90e793f0.jpg" alt="" style="display:block;margin:0 auto" />

<h3>Offsets</h3>
<p>Every message written to a Partition is assigned a monotonically increasing integer called an <strong>Offset</strong> (0, 1, 2, 3...). The offset uniquely identifies a message within its Partition.</p>
<p>Consumers <strong>commit their current offset</strong> to Kafka (stored in an internal topic called <code>__consumer_offsets</code>). This means:</p>
<ul>
<li><p>If a Consumer crashes and restarts, it resumes from its last committed offset  no message is lost.</p>
</li>
<li><p>A Consumer can deliberately <strong>seek</strong> to any offset, enabling <strong>message replay</strong>. This is huge for debugging, reprocessing, and backfill scenarios that would be impossible with traditional queues.</p>
</li>
</ul>
<pre><code class="language-java">// Seek to beginning for replay (Java)
consumer.seekToBeginning(consumer.assignment());

// Or seek to a specific offset
consumer.seek(new TopicPartition("order-events", 0), 1000L);
</code></pre>
<h3>Choosing the Right Number of Partitions</h3>
<p>This is one of the most consequential decisions in Kafka design. Rules of thumb:</p>
<ul>
<li><p><strong>Start with</strong> <code>max(throughput_MB/s / 10, num_consumer_instances)</code> as a baseline.</p>
</li>
<li><p>More partitions = more parallelism, but also more open file handles and longer leader election time.</p>
</li>
<li><p>You can <strong>increase</strong> partitions later, but you <strong>cannot decrease</strong> them  plan ahead.</p>
</li>
<li><p>If ordering across all messages matters (e.g., financial ledger), use <strong>1 partition</strong> (and accept the throughput limit).</p>
</li>
</ul>
<h3>Message Retention</h3>
<p>By default, Kafka retains messages for <strong>7 days</strong> regardless of whether they've been consumed. This is configurable per-topic:</p>
<pre><code class="language-properties"># Keep messages for 30 days
log.retention.hours=720

# Or keep until log hits 50GB
log.retention.bytes=53687091200

# Compact mode: keep only the latest value per key (event sourcing)
log.cleanup.policy=compact
</code></pre>
<p><strong>Log compaction</strong> deserves special attention. Instead of deleting old messages by time, Kafka retains the most recent message per key, enabling it to serve as a persistent state store  a foundation for the <strong>Event Sourcing</strong> pattern.</p>
<hr />
<h2>6. Replication and Fault Tolerance  Unstoppable by Design</h2>
<h3>Replication Factor</h3>
<p>Every Partition is replicated across multiple Brokers. The <strong>replication factor</strong> (recommended: 3 for production) determines how many copies exist. With a replication factor of 3:</p>
<ul>
<li><p>1 Broker is the <strong>Leader</strong> (handles all reads and writes for that partition).</p>
</li>
<li><p>2 Brokers are <strong>Followers</strong> (replicate data from the Leader).</p>
</li>
</ul>
<p>If the Leader Broker fails, one of the Followers is automatically elected as the new Leader from the <strong>ISR (In-Sync Replica)</strong> list  the set of replicas that are fully caught up with the Leader's log.</p>
<h3>The <code>acks</code> Setting  Durability vs. Throughput</h3>
<p>The Producer's <code>acks</code> configuration controls when a write is considered "done":</p>
<table>
<thead>
<tr>
<th>Setting</th>
<th>Behavior</th>
<th>Latency</th>
<th>Risk</th>
</tr>
</thead>
<tbody><tr>
<td><code>acks=0</code></td>
<td>Fire-and-forget, no acknowledgment</td>
<td>Lowest</td>
<td>Data loss on broker crash</td>
</tr>
<tr>
<td><code>acks=1</code></td>
<td>Leader acknowledges receipt</td>
<td>Medium</td>
<td>Data loss if leader fails before replication</td>
</tr>
<tr>
<td><code>acks=all</code> (or <code>-1</code>)</td>
<td>All ISRs acknowledge</td>
<td>Highest</td>
<td>No data loss; highest durability</td>
</tr>
</tbody></table>
<p>For most production use cases, <code>acks=all</code> combined with <code>min.insync.replicas=2</code> is the gold standard:</p>
<pre><code class="language-properties"># Producer config
acks=all
retries=Integer.MAX_VALUE
enable.idempotence=true  # Exactly-once semantics for producer

# Broker/Topic config
min.insync.replicas=2    # At least 2 ISRs must acknowledge
</code></pre>
<h3>Exactly-Once Semantics</h3>
<p>Since Kafka 0.11, the platform supports <strong>exactly-once semantics (EOS)</strong> end-to-end  meaning a message is processed exactly once even in the face of producer retries or consumer crashes. This requires:</p>
<ol>
<li><p><strong>Idempotent Producer</strong>: Deduplicates retries using a producer ID + sequence number.</p>
</li>
<li><p><strong>Transactional API</strong>: Atomically writes to multiple partitions and commits consumer offsets.</p>
</li>
</ol>
<p>This was a significant milestone that made Kafka viable for financial transaction processing where double-processing is catastrophic.</p>
<hr />
<h2>7. The Kafka Ecosystem  Beyond Basic Messaging</h2>
<p>Kafka's ecosystem extends far beyond the core broker. These four components transform it from a message bus into a complete data platform.</p>
<h3>Producer API &amp; Consumer API</h3>
<p>The fundamental building blocks, as discussed. Available in Java (official), and community clients for Python (<a href="https://github.com/confluentinc/confluent-kafka-python">confluent-kafka-python</a>), Go (<a href="https://github.com/IBM/sarama">sarama</a>), Node.js (<a href="https://kafka.js.org/">kafkajs</a>), Rust, and many more.</p>
<h3>Kafka Streams</h3>
<p><a href="https://kafka.apache.org/documentation/streams/">Kafka Streams</a> is a <strong>client-side library</strong> (not a separate cluster) for building real-time stream processing applications in Java/Kotlin. Key characteristics:</p>
<ul>
<li><p>Runs embedded in your application  no separate cluster infrastructure needed.</p>
</li>
<li><p>Provides stateful operations: windowed aggregations, joins, group-by.</p>
</li>
<li><p>Exactly-once processing semantics.</p>
</li>
<li><p>Handles partition rebalancing automatically.</p>
</li>
</ul>
<pre><code class="language-java">// Count orders per user in a 5-minute tumbling window
StreamsBuilder builder = new StreamsBuilder();
builder.stream("order-events", Consumed.with(Serdes.String(), orderSerde))
    .groupByKey()
    .windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5)))
    .count()
    .toStream()
    .to("order-counts-per-user");
</code></pre>
<p><strong>When to use it:</strong> When you need lightweight stream processing embedded in your existing service, without the overhead of deploying a separate Flink or Spark cluster.</p>
<h3>Kafka Connect</h3>
<p><a href="https://docs.confluent.io/platform/current/connect/index.html">Kafka Connect</a> is a framework for building scalable, reliable data pipelines between Kafka and external systems  without writing custom producer/consumer code. It uses <strong>connectors</strong>:</p>
<ul>
<li><p><strong>Source Connectors:</strong> Pull data into Kafka (e.g., <a href="https://debezium.io/">Debezium</a> for Change Data Capture from MySQL/PostgreSQL, S3 source, Salesforce source).</p>
</li>
<li><p><strong>Sink Connectors:</strong> Push data out of Kafka (e.g., Elasticsearch sink, S3 sink, JDBC sink for databases).</p>
</li>
</ul>
<p>The <a href="https://www.confluent.io/hub/">Confluent Hub</a> lists hundreds of community and commercial connectors. In most data platform architectures, Connect handles the "plumbing," freeing engineers to focus on business logic.</p>
<h3>ksqlDB</h3>
<p><a href="https://ksqldb.io/">ksqlDB</a> allows you to query and transform streaming data using <strong>SQL-like syntax</strong>, eliminating the need to write Java/Streams code for many common patterns:</p>
<pre><code class="language-sql">-- Create a stream of orders
CREATE STREAM orders (
    order_id VARCHAR,
    user_id VARCHAR,
    amount DOUBLE
) WITH (KAFKA_TOPIC='order-events', VALUE_FORMAT='JSON');

-- Real-time aggregation: total spend per user in last 10 minutes
SELECT user_id, SUM(amount) as total_spend
FROM orders
WINDOW TUMBLING (SIZE 10 MINUTES)
GROUP BY user_id
EMIT CHANGES;
</code></pre>
<p>This is particularly powerful for operational analytics teams who know SQL but not Java.</p>
<hr />
<h2>8. Why Kafka Is Absurdly Fast</h2>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/f1314f90-dd5c-49ff-94db-996794741c4d.jpg" alt="" style="display:block;margin:0 auto" />

<p>Kafka routinely achieves <strong>2 million+ messages per second</strong> per cluster with <strong>sub-millisecond latency</strong>. This isn't magic  it's a set of deliberate engineering decisions.</p>
<h3>1. Sequential I/O</h3>
<p>Kafka writes to disk using <strong>sequential append</strong> to a log file. Sequential disk I/O on modern SSDs is 100x faster than random access. Counterintuitively, Kafka's disk-based persistence is <em>faster</em> than many in-memory systems that use random data structures (hash maps, trees).</p>
<h3>2. Zero-Copy Transfer</h3>
<p>When sending data from disk to a network socket, the naive approach involves 4 data copies: disk  kernel buffer  user space  kernel socket buffer  network. Kafka uses the OS <a href="https://man7.org/linux/man-pages/man2/sendfile.2.html"><code>sendfile(2)</code></a> system call to short-circuit this to 2 copies (disk  kernel buffer  network), cutting CPU cycles for data transfer roughly in half.</p>
<h3>3. Batching</h3>
<p>Producers don't send one message at a time. They accumulate messages in a buffer and send them as a batch, amortizing network round-trip overhead across many messages. This is controlled by <code>linger.ms</code> and <code>batch.size</code>:</p>
<pre><code class="language-properties"># Wait up to 5ms or until 16KB buffer is full, whichever comes first
linger.ms=5
batch.size=16384
</code></pre>
<h3>4. Compression</h3>
<p>Kafka supports compressing entire batches using <code>gzip</code>, <code>snappy</code>, <code>lz4</code>, or <code>zstd</code>. Compression happens at the Producer, stays compressed through the broker (Kafka doesn't re-compress), and decompresses only at the Consumer. On text-heavy payloads (JSON, log lines), <code>lz4</code> or <code>snappy</code> can reduce message size by 6080%, dramatically reducing network bandwidth.</p>
<pre><code class="language-properties"># Producer compression config
compression.type=lz4
</code></pre>
<h3>5. OS Page Cache</h3>
<p>Kafka aggressively relies on the OS page cache rather than managing its own memory pool. This means Kafka brokers should be provisioned with <strong>lots of RAM</strong>  not for JVM heap (keep heap small, 48GB), but for the OS to use as disk cache. Reads from recently-written data almost never touch physical disk.</p>
<hr />
<h2>9. Real-World Use Cases</h2>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/350e3cd2-b69c-4a48-8e5a-d0abc63a01f7.jpg" alt="" style="display:block;margin:0 auto" />

<h3>1. Real-Time Analytics</h3>
<p><strong>Netflix</strong> uses Kafka as its <a href="https://netflixtechblog.com/kafka-inside-keystone-pipeline-dd5aeabaf6bb">Keystone Pipeline</a>, processing hundreds of billions of events daily. Clickstream data flows through Kafka into Spark and Druid for real-time recommendation updates and A/B test analysis.</p>
<h3>2. Log Aggregation</h3>
<p>The classic use case. Hundreds of application servers emit logs  Kafka acts as a buffer  Logstash/Fluentd consumers forward to Elasticsearch or Splunk. Kafka's retention means a spike in log volume won't cause data loss even if the downstream ELK stack is temporarily overwhelmed.</p>
<h3>3. Microservices Decoupling (Event-Driven Architecture)</h3>
<p>Services publish domain events to Kafka topics. Other services react to those events independently. No direct service-to-service calls, no tight coupling, no synchronous dependencies. An <code>order-placed</code> event on a Kafka topic can trigger inventory reservation, payment processing, and email notification  all independently, all at their own pace.</p>
<h3>4. Event Sourcing / CQRS</h3>
<p>Using log compaction, Kafka becomes a durable event store. Every state change is an event; to reconstruct the current state of any entity, replay its events from the beginning (or from a snapshot). <a href="https://martinfowler.com/eaaDev/EventSourcing.html">Martin Fowler's Event Sourcing pattern</a> maps naturally to Kafka's append-only log.</p>
<h3>5. Financial Transactions and Fraud Detection</h3>
<p><strong>PayPal</strong> processes millions of payment events through Kafka, enabling real-time fraud detection models to evaluate transactions in milliseconds. <strong>Uber's surge pricing</strong> and <strong>driver matching</strong> rely on Kafka to propagate location and demand events system-wide in near-real-time. The combination of high throughput, low latency, exactly-once semantics, and durability makes Kafka uniquely suited to fintech.</p>
<hr />
<h2>10. Kafka vs. RabbitMQ vs. Amazon Kinesis {#comparison}</h2>
<p>This is the question every architect faces. Here's an honest comparison:</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Apache Kafka</th>
<th>RabbitMQ</th>
<th>Amazon Kinesis</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Primary Use Case</strong></td>
<td>Large-scale streaming &amp; event logs</td>
<td>Complex routing &amp; task queues</td>
<td>AWS-native streaming</td>
</tr>
<tr>
<td><strong>Throughput</strong></td>
<td>Millions/sec (top tier)</td>
<td>Tenshundreds of thousands/sec</td>
<td>Millions/sec (shard-dependent)</td>
</tr>
<tr>
<td><strong>Message Retention</strong></td>
<td>Configurable (infinite possible)</td>
<td>Deleted after consumption</td>
<td>Up to 1 year (default 24h)</td>
</tr>
<tr>
<td><strong>Scaling</strong></td>
<td>Horizontal via Partitions</td>
<td>Manual clustering</td>
<td>Shard adjustment (AWS managed)</td>
</tr>
<tr>
<td><strong>Operational Cost</strong></td>
<td>High (self-managed) / Low (managed)</td>
<td>Medium</td>
<td>Low (fully managed)</td>
</tr>
<tr>
<td><strong>Protocol</strong></td>
<td>Custom binary (TCP)</td>
<td>AMQP, STOMP, MQTT</td>
<td>AWS Custom API</td>
</tr>
<tr>
<td><strong>Message Replay</strong></td>
<td> Native</td>
<td> Not supported</td>
<td> Supported</td>
</tr>
<tr>
<td><strong>Consumer Groups</strong></td>
<td> Multiple independent groups</td>
<td>Partial (via exchanges)</td>
<td> Multiple apps</td>
</tr>
<tr>
<td><strong>Ordering Guarantee</strong></td>
<td>Per-partition</td>
<td>Per-queue</td>
<td>Per-shard</td>
</tr>
<tr>
<td><strong>Best For</strong></td>
<td>High throughput, replay, multi-cloud</td>
<td>Complex routing, priority queues</td>
<td>Easy setup in AWS ecosystem</td>
</tr>
</tbody></table>
<h3>The Honest Take</h3>
<ul>
<li><p><strong>Choose RabbitMQ</strong> when you need sophisticated message routing (topic exchanges, header-based routing, dead-letter queues with complex retry logic) and your throughput is under ~100K messages/sec. It's simpler to operate at small scale.</p>
</li>
<li><p><strong>Choose Amazon Kinesis</strong> when you're fully committed to AWS, want zero operational overhead, and don't need multi-cloud portability. The managed experience is excellent, but you're locked in.</p>
</li>
<li><p><strong>Choose Kafka</strong> when you need replay, multiple independent consumers, 100K+ messages/sec, cross-cloud deployment, or event sourcing patterns. The operational overhead is real (mitigated by <a href="https://aws.amazon.com/msk/">Amazon MSK</a>, <a href="https://www.confluent.io/confluent-cloud/">Confluent Cloud</a>, or <a href="https://aiven.io/kafka">Aiven</a>), but the capability ceiling is the highest of the three.</p>
</li>
</ul>
<hr />
<h2>11. When Should You Actually Choose Kafka?</h2>
<p>A decision framework to cut through the hype:</p>
<h3> Choose Kafka When:</h3>
<ul>
<li><p>You need to process <strong>100,000+ messages per second</strong> reliably.</p>
</li>
<li><p>You need <strong>message replay</strong>  the ability to reprocess historical events (auditing, debugging, backfill).</p>
</li>
<li><p><strong>Multiple independent services</strong> (consumer groups) need to consume the same event stream.</p>
</li>
<li><p>You're building on <strong>multi-cloud or on-premises</strong> infrastructure where AWS lock-in is a concern.</p>
</li>
<li><p>You're adopting <strong>Event Sourcing, CQRS</strong>, or <strong>Change Data Capture</strong> (CDC) patterns.</p>
</li>
<li><p>Your data retention requirements extend <strong>beyond a few hours</strong> (analytics, compliance).</p>
</li>
</ul>
<h3> Consider Alternatives When:</h3>
<ul>
<li><p>You just need a <strong>simple task queue</strong> with a handful of workers  RabbitMQ is simpler.</p>
</li>
<li><p>You're <strong>fully on AWS</strong> and want minimal operational overhead  Kinesis or SQS.</p>
</li>
<li><p>Message volume is low but you need <strong>complex routing logic</strong> (header-based, topic-exchange fan-out)  RabbitMQ's exchange model is more expressive.</p>
</li>
<li><p>Your team has <strong>limited Kafka expertise</strong> and no managed service budget  The operational learning curve is steep.</p>
</li>
</ul>
<blockquote>
<p><strong>Kafka is "heavy artillery."</strong> It's overkill for small problems. It's unbeatable for large-scale, high-reliability, multi-consumer scenarios.</p>
</blockquote>
<hr />
<h2>12. Getting Started in 15 Minutes</h2>
<h3>Option A: Local Setup via Docker Compose</h3>
<p>The fastest path to a running Kafka:</p>
<pre><code class="language-yaml"># docker-compose.yml (KRaft mode, no ZooKeeper)
version: '3.8'
services:
  kafka:
    image: confluentinc/cp-kafka:7.6.0
    container_name: kafka
    ports:
      - "9092:9092"
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_PROCESS_ROLES: broker,controller
      KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
      KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
      CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk
</code></pre>
<pre><code class="language-bash">docker compose up -d
</code></pre>
<h3>Create a Topic</h3>
<pre><code class="language-bash">docker exec kafka kafka-topics \
  --create \
  --topic my-topic \
  --partitions 3 \
  --replication-factor 1 \
  --bootstrap-server localhost:9092
</code></pre>
<h3>Producer &amp; Consumer (Python)</h3>
<pre><code class="language-python"># pip install confluent-kafka
from confluent_kafka import Producer, Consumer

# Producer
producer = Producer({'bootstrap.servers': 'localhost:9092'})
producer.produce('my-topic', key='user-123', value='{"event":"page_view","page":"/home"}')
producer.flush()

# Consumer
consumer = Consumer({
    'bootstrap.servers': 'localhost:9092',
    'group.id': 'analytics-service',
    'auto.offset.reset': 'earliest'
})
consumer.subscribe(['my-topic'])

while True:
    msg = consumer.poll(timeout=1.0)
    if msg and not msg.error():
        print(f"Partition {msg.partition()}, Offset {msg.offset()}: {msg.value().decode()}")
</code></pre>
<h3>Producer &amp; Consumer (Spring Boot / Java)</h3>
<pre><code class="language-xml">&lt;!-- pom.xml --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.kafka&lt;/groupId&gt;
    &lt;artifactId&gt;spring-kafka&lt;/artifactId&gt;
&lt;/dependency&gt;
</code></pre>
<pre><code class="language-yaml"># application.yml
spring:
  kafka:
    bootstrap-servers: localhost:9092
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
    consumer:
      group-id: analytics-service
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
</code></pre>
<h3>Option B: Managed Kafka (Zero Ops)</h3>
<p>If you want to skip cluster management entirely:</p>
<table>
<thead>
<tr>
<th>Service</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td><a href="https://www.confluent.io/confluent-cloud/">Confluent Cloud</a></td>
<td>Richest ecosystem, free tier available</td>
</tr>
<tr>
<td><a href="https://aws.amazon.com/msk/">Amazon MSK</a></td>
<td>Best if already on AWS</td>
</tr>
<tr>
<td><a href="https://aiven.io/kafka">Aiven for Kafka</a></td>
<td>Multi-cloud (AWS/GCP/Azure), generous free trial</td>
</tr>
<tr>
<td><a href="https://upstash.com/docs/kafka/overall/getstarted">Upstash Kafka</a></td>
<td>Serverless, pay-per-message, great for dev/test</td>
</tr>
</tbody></table>
<p>For production systems with serious throughput, Amazon MSK Serverless or Confluent Cloud will get you from zero to production in an afternoon.</p>
<hr />
<h2>13. Summary</h2>
<p>Let's bring it home. Here's what every engineer should internalize about Kafka:</p>
<ul>
<li><p><strong>Kafka is the "Data Highway"</strong>  a distributed streaming platform built on five primitives: Producers, Topics, Partitions, Consumers, and Brokers. Everything else is built on top of these.</p>
</li>
<li><p><strong>Its performance secrets</strong> are architectural: sequential I/O, zero-copy transfers via <code>sendfile()</code>, producer-side batching, and aggressive OS page cache utilization. The result: 2M+ messages/sec with sub-millisecond latency.</p>
</li>
<li><p><strong>Partitions are the unit of scalability and ordering.</strong> Design your partition key carefully. Ordering is guaranteed per-partition, not globally. More partitions = more consumer parallelism.</p>
</li>
<li><p><strong>Consumer Groups unlock fan-out.</strong> Multiple independent services can each read the same topic at their own pace. This is the architectural enabler of loosely coupled microservices.</p>
</li>
<li><p><strong>KRaft replaces ZooKeeper</strong> in modern Kafka deployments. If you're starting fresh, run KRaft mode  it's simpler, faster to operate, and required from Kafka 4.0 onward.</p>
</li>
<li><p><strong>The ecosystem extends far beyond messaging:</strong> Kafka Streams for in-process stream processing, Kafka Connect for zero-code data pipelines, and ksqlDB for SQL-based stream queries.</p>
</li>
<li><p><strong>Kafka wins on throughput, replay, and multi-consumer use cases.</strong> It loses on operational simplicity (mitigated by managed services) and complex routing (where RabbitMQ excels).</p>
</li>
<li><p><strong>Choose it deliberately.</strong> Kafka is heavy artillery. Deploy it when your problem is truly at scale, not because it's fashionable.</p>
</li>
</ul>
<hr />
<p><em>Have questions or war stories from running Kafka in production? Drop them in the comments  I'd love to compare notes.</em></p>
<hr />
<h3>References &amp; Further Reading</h3>
<ul>
<li><p><a href="https://kafka.apache.org/documentation/">Apache Kafka Official Documentation</a></p>
</li>
<li><p><a href="https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying">The Log: What every software engineer should know about real-time data's unifying abstraction</a>  Jay Kreps (LinkedIn)</p>
</li>
<li><p><a href="https://www.oreilly.com/library/view/kafka-the-definitive/9781492043072/">Kafka: The Definitive Guide, 2nd Ed.</a>  O'Reilly</p>
</li>
<li><p><a href="https://developer.confluent.io/tutorials/">Confluent Developer: Kafka Tutorials</a></p>
</li>
<li><p><a href="https://developer.confluent.io/learn/kraft/">KRaft: Apache Kafka Without ZooKeeper</a></p>
</li>
<li><p><a href="https://debezium.io/documentation/">Debezium: Change Data Capture with Kafka Connect</a></p>
</li>
<li><p><a href="https://netflixtechblog.com/kafka-inside-keystone-pipeline-dd5aeabaf6bb">Netflix Tech Blog: Kafka Inside Keystone Pipeline</a></p>
</li>
<li><p><a href="https://eng.uber.com/reliable-reprocessing/">Uber Engineering: Reliable Reprocessing with Kafka</a></p>
</li>
<li><p><a href="https://martinfowler.com/eaaDev/EventSourcing.html">Martin Fowler: Event Sourcing</a></p>
</li>
</ul>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-06-22-1221</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-06-22-1221</guid><category><![CDATA[Apache Kafka]]></category><category><![CDATA[distributed system]]></category><category><![CDATA[backend]]></category><category><![CDATA[event-driven-architecture]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Developing with AI Agents: A Practical Field Guide to Codex, Claude Code, and Claude Cowork]]></title><description><![CDATA[<p>If you've shipped anything with an AI coding agent in the last few months, you already know the feeling: you write three sentences, walk away to get coffee, and come back to a pull request with a diff, a test run, and a changelog entry. That's a different relationship to your codebase than the one most of us grew up with, and it's worth being deliberate about how we use it.</p>
<p>This post is a field guide  not a press release. It's about the three agent tools an individual contractor or small team is most likely to reach for right now (OpenAI's Codex, Anthropic's Claude Code, and Anthropic's Claude Cowork), how to choose between them, and  more importantly  the operating discipline that determines whether delegating to an agent makes you faster or just makes your mistakes happen faster.</p>
<p>A quick caveat before we start: model versions, benchmark scores, and pricing in this space change on a roughly monthly cadence. I've linked sources throughout so you can check current numbers yourself; treat anything with a specific percentage or dollar figure as a snapshot, not a permanent fact.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/developing-with-ai-agents-codex-claude-code-and-cowork-practical-guide">https://speakerdeck.com/x5gtrn/developing-with-ai-agents-codex-claude-code-and-cowork-practical-guide</a></p>

<h2>Why This Shift Happened Now</h2>
<p>For most of the last few years, "AI coding help" meant a chat window: you pasted in a function, asked a question, got an explanation or a snippet back, and did the rest yourself by hand  copy, paste, run, debug, repeat.</p>
<p>What changed is that models got good enough at multi-step tool use that they could be trusted to operate <em>inside</em> a development loop rather than just narrate it: clone a repo, read the actual files, run the test suite, interpret the failures, edit code, run the tests again, and open a pull request  largely without a human re-typing every intermediate step. OpenAI describes Codex as a tool that lets engineers "offload repetitive, well-scoped tasks, like refactoring, renaming, and writing tests" in its <a href="https://openai.com/index/introducing-codex/">original launch post</a>, and that framing  agent as coworker for bounded units of work, not oracle that answers questions  is the right mental model for all three tools covered here.</p>
<p>The practical consequence for us as engineers is a role shift. The bottleneck used to be typing speed and syntax recall. Now it's increasingly <strong>the quality of the instructions you give the agent and the rigor with which you review what comes back</strong>. That's a less glamorous skill than "knows fifteen design patterns," but it's the one that actually predicts whether your week with an agent goes well.</p>
<h2>Chat Tool vs. Coding Agent: What Actually Changed</h2>
<p>It's worth being precise about the distinction, because a lot of frustration with agent tools comes from treating them like a smarter chat window.</p>
<table>
<thead>
<tr>
<th></th>
<th>AI Chat</th>
<th>AI Coding Agent</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Scope</strong></td>
<td>Questions, explanations, snippets</td>
<td>Investigates a real repo, edits real files</td>
</tr>
<tr>
<td><strong>Memory</strong></td>
<td>The current conversation only</td>
<td>The actual codebase, working tree, git history</td>
</tr>
<tr>
<td><strong>Output</strong></td>
<td>Text and code blocks you paste in</td>
<td>Diffs, commits, pull requests, test results</td>
</tr>
<tr>
<td><strong>Execution</strong></td>
<td>None  you run everything yourself</td>
<td>Runs tests, linters, builds, git commands</td>
</tr>
<tr>
<td><strong>Your involvement</strong></td>
<td>Required at every step</td>
<td>Delegatable per task, with checkpoints</td>
</tr>
</tbody></table>
<p>The shift from "generates a snippet" to "investigates, edits, tests, and opens a PR" is the entire reason this generation of tools is worth restructuring your workflow around. It's also exactly why the failure modes are different and, frankly, scarier  an agent that's wrong about a snippet wastes your time; an agent that's wrong about a destructive shell command or a schema migration can cost you a production incident. More on that below.</p>
<h2>Three Tools, Three Philosophies</h2>
<h3>OpenAI Codex  the asynchronous cloud agent</h3>
<p>Codex (the 2025 relaunch, not the original 2021 Codex model behind early GitHub Copilot) is built around <strong>isolated, asynchronous execution</strong>. Each task  "add test coverage for the auth module," "upgrade this dependency," "fix the bug described in this issue"  runs in its own cloud sandbox preloaded with your repository, with its own git worktree so parallel tasks never collide. You submit a task, go do something else, and come back five to thirty minutes later to a reviewable result: command logs, test output, and a diff or PR.</p>
<p>Two things make Codex distinctive in practice:</p>
<ul>
<li><p><strong>GitHub-native review loops.</strong> Commenting <code>@codex review</code> on a pull request triggers an automated review pass, and issue-to-PR automation means a well-written GitHub issue can become a draft PR without anyone opening an editor.</p>
</li>
<li><p><strong>Genuine parallelism.</strong> Because tasks are sandboxed and isolated, you can fire off several at once  a refactor, a test-coverage task, and a dependency bump  and they won't step on each other's working copies, as OpenAI's <a href="https://openai.com/codex/">Codex product page</a> and various comparison write-ups on its <a href="https://www.morphllm.com/comparisons/codex-vs-claude-code">subagent architecture</a> describe.</p>
</li>
</ul>
<p>That asynchronous, batch-oriented design is also its main limitation for certain work: it's a poor fit for tasks that need tight, interactive back-and-forth, like debugging something genuinely confusing where you want to redirect the agent every thirty seconds.</p>
<h3>Claude Code  the interactive terminal partner</h3>
<p>Claude Code takes the opposite default: it runs <strong>locally</strong>, in your terminal (with IDE and browser surfaces available too), and it asks for confirmation before consequential actions. Nothing leaves your machine unless you've configured it to.</p>
<p>That local, confirm-before-acting posture makes it well suited to the work Codex is weaker at: deep, interactive investigation of an unfamiliar codebase, multi-turn debugging where each step changes your understanding of the problem, and step-by-step refactors where you want to review the diff after every file rather than at the end. A <code>CLAUDE.md</code> file at the root of your project gives it durable, repo-specific context  coding conventions, prohibited actions, the exact command to run tests  that persists across the session instead of being re-explained every time, which matters a great deal once your sessions run long. (See Anthropic's <a href="https://code.claude.com/docs/en/whats-new">Claude Code documentation</a> for the current feature set, which has been shipping updates at an unusually fast clip this year.)</p>
<h3>Claude Cowork  the same idea, for non-engineers</h3>
<p>Cowork is Anthropic's answer to a fair question: if "an agent that investigates, acts, and reports back" is this useful for code, why should it be limited to people who write code? Launched in January 2026 and built into the Claude desktop app, Cowork applies the same agentic loop  read your files, figure out a plan, execute multi-step work, report back  to research, document creation, and business workflows, with no terminal required, as described on <a href="https://claude.com/product/cowork">Anthropic's Cowork product page</a>.</p>
<p>What makes it relevant even for engineering-heavy teams is its plugin ecosystem. Anthropic shipped <a href="https://www.reworked.co/collaboration-productivity/anthropic-adds-plugins-to-claude-cowork/">11 open-source plugins</a> at launch  productivity, enterprise search, sales, and others  each bundling skills, connectors, and slash commands so Cowork shows up pre-loaded with domain context instead of starting from zero. If you're a one-person shop juggling client research, spec documents, and engineering work the way a lot of independent contractors do, Cowork is the tool for the research-and-documentation half of that workload, leaving Claude Code or Codex for the half that touches a repository. <a href="https://thenewstack.io/anthropic-brings-plugins-to-cowork/">The New Stack's coverage</a> of the plugin launch is a good orientation if you want the fuller picture.</p>
<h2>How to Choose: A Decision Table</h2>
<p>No single tool wins every axis. Here's the rough mapping I use day to day:</p>
<table>
<thead>
<tr>
<th>Task</th>
<th>Reach for</th>
<th>Why</th>
</tr>
</thead>
<tbody><tr>
<td>Investigating unfamiliar code</td>
<td>Claude Code</td>
<td>Deep, interactive local investigation</td>
</tr>
<tr>
<td>Small-to-medium implementation fix</td>
<td>Claude Code <em>or</em> Codex</td>
<td>Interactive vs. fire-and-forget  your call</td>
</tr>
<tr>
<td>Bug investigation / debugging</td>
<td>Claude Code</td>
<td>Narrow down hypotheses turn by turn</td>
</tr>
<tr>
<td>Adding test coverage</td>
<td>Codex</td>
<td>Parallelizes well, low need for interaction</td>
</tr>
<tr>
<td>Refactoring</td>
<td>Claude Code</td>
<td>Review the diff step by step as it goes</td>
</tr>
<tr>
<td>PR review</td>
<td>Codex</td>
<td><code>@codex review</code> automates the first pass</td>
</tr>
<tr>
<td>Technical research &amp; comparison docs</td>
<td>Claude Cowork</td>
<td>Research  organize  document in one task</td>
</tr>
<tr>
<td>Design notes / ADRs</td>
<td>Claude Cowork</td>
<td>Strong at structured document generation</td>
</tr>
<tr>
<td>README / spec drafting</td>
<td>Claude Cowork</td>
<td>Reads existing files, drafts consistent docs</td>
</tr>
</tbody></table>
<p>A useful shorthand: <strong>Codex for async batch work you can queue and walk away from, Claude Code for interactive work where you want to stay in the loop, Cowork for anything that ends in a document rather than a diff.</strong></p>
<h2>The Workflow That Actually Works</h2>
<p>The single most common cause of a bad outcome with any of these tools is skipping straight to "go implement this." The workflow that consistently produces good results looks like this:</p>
<ol>
<li><p><strong>Investigate.</strong> Ask the agent to understand the codebase and the blast radius of the change <em>before</em> touching anything.</p>
</li>
<li><p><strong>Propose a plan.</strong> Have it suggest an approach, not code.</p>
</li>
<li><p><strong>Review the plan.</strong>  human checkpoint. You approve the approach before any file gets touched.</p>
</li>
<li><p><strong>Implement in small steps.</strong> One feature or one file at a time, not a sprawling multi-file rewrite in one shot.</p>
</li>
<li><p><strong>Run tests.</strong> Confirm existing tests still pass.</p>
</li>
<li><p><strong>Review the diff.</strong>  human checkpoint. You read every line. Always.</p>
</li>
<li><p><strong>Revise if needed.</strong> Feed back specific issues; let it re-implement.</p>
</li>
<li><p><strong>Final decision.</strong>  human checkpoint. Merging and releasing stays a human call.</p>
</li>
</ol>
<p>Notice that three of the eight steps are explicit human checkpoints. That's not friction for its own sake  it's where the actual leverage of "agent as partner, not autopilot" lives. Skipping straight from a one-line request to step 4 is the root cause of nearly every bad agent experience I've had or read about.</p>
<h2>Eight Principles for Mastering AI Agents</h2>
<p>These read like common sense in retrospect, which is exactly why they're easy to forget mid-task:</p>
<ol>
<li><p><strong>Don't jump straight to implementation.</strong> Have it investigate and propose a change plan first.</p>
</li>
<li><p><strong>One task, one purpose.</strong> Don't bundle three unrelated changes into a single request  you lose the ability to evaluate any one of them cleanly.</p>
</li>
<li><p><strong>Clarify the scope of changes explicitly.</strong> State which files or directories are in bounds and which are not.</p>
</li>
<li><p><strong>State constraints upfront.</strong> "No API spec changes," "no new dependencies," whatever applies  say it before the agent starts, not after you're reviewing a surprising diff.</p>
</li>
<li><p><strong>Always instruct test execution.</strong> Explicitly ask for "run the tests and report the results"  don't assume it happened.</p>
</li>
<li><p><strong>Humans always review diffs.</strong> Never merge on trust alone, no matter how clean the summary looks.</p>
</li>
<li><p><strong>Don't leave major design decisions to the AI.</strong> Architecture and security calls are yours to make.</p>
</li>
<li><p><strong>Explicitly state what must <em>not</em> be done.</strong> Write prohibited actions out in plain language; don't rely on the agent inferring them.</p>
</li>
</ol>
<h2>Practical Prompt Templates</h2>
<p>Principles are easy to nod along with and easy to forget under deadline pressure, so here are three prompts I actually keep on hand, adapted to whichever tool I'm using that day.</p>
<p><strong>1. Codebase investigation request</strong> (always the first move on unfamiliar code):</p>
<pre><code class="language-plaintext">Investigate this repository and explain the overall structure of
the login process. Do not edit any files yet.

Please check the following in particular:
- Entry point for authentication (endpoints)
- Related APIs and middleware
- DB tables and schema
- Error handling approach
- Presence and coverage of tests

Finally, propose a safe procedure for making modifications.
</code></pre>
<p>The two load-bearing lines here are "do not edit any files yet" and the explicit checklist. Without the first, an agent that's confident in its read of the code may start "helpfully" fixing things you didn't ask it to touch. Without the second, investigation tends to stop at the first plausible-looking answer instead of actually covering the area.</p>
<p><strong>2. Implementation request, minimal-diff principle:</strong></p>
<pre><code class="language-plaintext">Based on the investigation results above, please fix this with a
minimal diff.

Constraints:
- Do not change the existing API specification
- All existing tests must pass
- Do not add new dependency libraries
- Present the list of target files before making changes
- Show the test command to run after implementation
- Only modify files under src/auth/
</code></pre>
<p>"Minimal diff" is doing a lot of work in that first line. Left unconstrained, agents  like a lot of enthusiastic junior engineers  will sometimes "improve" adjacent code while they're in there. Pinning the file scope (<code>src/auth/</code> here) is the single highest-leverage line in this whole template.</p>
<p><strong>3. Diff review request</strong> (have the agent review its own work before you do):</p>
<pre><code class="language-plaintext">Please review the current diff.

Review criteria:
- Does it satisfy the specification?
- Does it break any existing functionality?
- Are there any security issues?
- Does it contain any unnecessary changes?
- Is there insufficient test coverage?

If there are issues, classify them by severity: High / Medium / Low.
If there are High severity issues, also provide a fix proposal.
</code></pre>
<p>This doesn't replace your own review  see Principle 6 above  but a structured self-review pass catches a meaningful fraction of issues before they ever reach your eyes, and the severity classification helps you triage your own attention when you do look.</p>
<h2>Failure Patterns You Will Eventually Hit</h2>
<p>A few classic mistakes show up across every team I've talked to or read about that's adopted these tools, along with the countermeasure that actually works:</p>
<table>
<thead>
<tr>
<th>Failure pattern</th>
<th>Countermeasure</th>
</tr>
</thead>
<tbody><tr>
<td>Modifying unrelated files</td>
<td>Explicitly specify target files/directories</td>
</tr>
<tr>
<td>Interpreting specs arbitrarily</td>
<td>State constraints and success criteria upfront</td>
</tr>
<tr>
<td>Treating incomplete tests as done</td>
<td>Mandate "run tests and report results"</td>
</tr>
<tr>
<td>Changing DB schema or API spec without permission</td>
<td>List prohibited changes at the beginning</td>
</tr>
<tr>
<td>Adding dependency libraries without permission</td>
<td>Explicitly state "no new library additions"</td>
</tr>
<tr>
<td>Making overly large changes at once</td>
<td>Split into one task, one purpose</td>
</tr>
<tr>
<td>Executing commands with security risks</td>
<td>Use confirmation mode, minimize permissions</td>
</tr>
</tbody></table>
<p>Every one of these traces back to the same root cause: an instruction that was vaguer than it felt at the time you wrote it. "Fix the login process" feels specific until an agent with full filesystem access starts interpreting it.</p>
<h2>Minimizing Security Risk: Permission Hygiene</h2>
<p>A short, non-negotiable list:</p>
<p><strong>Never:</strong></p>
<ul>
<li><p>Paste API keys, tokens, or credentials into a prompt</p>
</li>
<li><p>Grant direct permission to operate on production environments</p>
</li>
<li><p>Allow destructive commands (<code>rm -rf</code>, <code>DROP TABLE</code>, etc.) without confirmation</p>
</li>
</ul>
<p><strong>Do:</strong></p>
<ul>
<li><p>Start in suggestion/confirmation mode, not auto-execute</p>
</li>
<li><p>Default to read-only permissions and expand only as trust is earned</p>
</li>
<li><p>Allow automatic execution only in staging environments</p>
</li>
<li><p>Manage secrets via environment variables, never inline in prompts</p>
</li>
<li><p>Review execution logs as a matter of habit, not just when something looks wrong</p>
</li>
</ul>
<p>If you only take one line from this section: the cost of typing <code>y</code> to confirm an action you didn't really read is identical, in the moment, to the cost of typing it after you did read it  and wildly different a week later if it was wrong.</p>
<h2>What Must Never Be Delegated</h2>
<p>No matter how capable these tools get, a few categories of decision stay human, full stop:</p>
<ul>
<li><p><strong>Requirements and spec decisions</strong>  what to build is a business judgment</p>
</li>
<li><p><strong>Architecture decisions</strong>  overall system design direction</p>
</li>
<li><p><strong>Security judgments</strong>  final evaluation of vulnerabilities and risk tolerance</p>
</li>
<li><p><strong>Quality standard decisions</strong>  what test coverage and review bar is acceptable</p>
</li>
<li><p><strong>Final review</strong>  a human reads the code before it merges</p>
</li>
<li><p><strong>Release decisions</strong>  final approval to ship to production</p>
</li>
</ul>
<p>The reasoning is straightforward: an agent optimizes within the scope of the instructions it's given, but business context, organizational constraints, and the judgment calls that trade one risk against another are not things you can fully specify in a prompt. That's not a temporary limitation to be patched in the next model release  it's a structural reason these decisions stay with the person accountable for the outcome.</p>
<h2>What These Tools Are Genuinely Great At</h2>
<p>On the other side of that line, there's a long list of work that's a very good candidate for active delegation:</p>
<ul>
<li><p>Investigating existing code and scoping the blast radius of a change</p>
</li>
<li><p>Small bug fixes and type-error cleanup</p>
</li>
<li><p>Writing and expanding test coverage</p>
</li>
<li><p>Drafting documentation  READMEs, API specs</p>
</li>
<li><p>Producing refactoring proposals for human review</p>
</li>
<li><p>Assisting with a first-pass PR review</p>
</li>
<li><p>Eliminating duplication and routine cleanup</p>
</li>
<li><p>Mechanical conversions (adding type annotations, sync-to-async migrations, etc.)</p>
</li>
</ul>
<p>This is where the time savings actually materialize, and it's not subtle. OpenAI describes Codex inside its own engineering org as the default tool for "repetitive, well-scoped tasks, like refactoring, renaming, and writing tests" that would otherwise break an engineer's focus, per the <a href="https://openai.com/index/introducing-codex/">Codex launch post</a>, and reporting on OpenAI's internal usage has described Codex generating the overwhelming majority of its own application code in some workflows, per <a href="https://leaddev.com/ai/openai-says-there-are-easily-1000x-engineers-now">LeadDev's interviews with the OpenAI team</a>. Independent benchmark trackers like <a href="https://www.vals.ai/benchmarks/swebench">vals.ai's SWE-bench Verified leaderboard</a> are worth bookmarking if you want current numbers rather than a stale snapshot  both Anthropic and OpenAI have been shipping model updates roughly monthly, and the leaderboard moves with them.</p>
<p>The honest framing for "30% automation" type stats you'll see quoted around the industry: directionally real, organization-specific, and not something to take as a guarantee for your own codebase. Your mileage genuinely will vary by language, test coverage, and how well-scoped your tickets already are.</p>
<h2>Tool-Specific Tips Worth Adopting</h2>
<p><strong>Codex:</strong></p>
<ul>
<li><p>Maintain an <code>AGENTS.md</code> documenting project rules, prohibited actions, and conventions  it loads automatically at the start of every session.</p>
</li>
<li><p>Use <code>@codex review</code> as a standing PR check rather than an occasional manual ask.</p>
</li>
<li><p>For genuinely hard bugs, the <code>--attempts</code> option generates multiple candidate solutions in parallel so you can pick the best one instead of iterating serially.</p>
</li>
</ul>
<p><strong>Claude Code:</strong></p>
<ul>
<li><p>Keep <code>CLAUDE.md</code> current  architecture overview, prohibited actions, the exact test command. This is what keeps behavior consistent across long sessions.</p>
</li>
<li><p>Use the dedicated Explore agent for "what does this file actually do?" questions before you commit to an implementation approach.</p>
</li>
<li><p><code>/compact</code> when context grows large in long sessions  it compresses history while preserving the working memory that matters.</p>
</li>
<li><p>Headless mode (<code>claude -p</code>) integrates into CI/CD pipelines and GitHub Actions for automated, scriptable runs.</p>
</li>
</ul>
<p><strong>Claude Cowork:</strong></p>
<ul>
<li><p>Lean on plugins for repeatable research-and-documentation workflows rather than re-explaining context every session.</p>
</li>
<li><p>Point it at local folders with existing specs so its drafts inherit your team's actual conventions instead of generic boilerplate.</p>
</li>
<li><p>Use it for the research  comparison table  ADR pipeline end to end in a single task; that handoff is where it earns its keep relative to a plain chat session.</p>
</li>
</ul>
<h2>Rolling This Out Across a Team</h2>
<p>If you're past the solo-experimentation phase:</p>
<ul>
<li><p><strong>Share</strong> <code>AGENTS.md</code> <strong>/</strong> <code>CLAUDE.md</code> <strong>in the repo.</strong> It doubles as onboarding material for new hires, human or otherwise.</p>
</li>
<li><p><strong>Automate PR review.</strong> Wire <code>@codex review</code> (or the Claude Code equivalent) into CI, and standardize the review criteria as a team rather than letting everyone invent their own.</p>
</li>
<li><p><strong>Optimize task distribution deliberately.</strong> Routine work  tests, type fixes, doc updates  goes to agents by default. Design and architecture discussions stay human-led.</p>
</li>
<li><p><strong>Hold the line on code review.</strong> AI-generated code goes through the exact same review process as human-written code. Every team member needs the skill of critically evaluating agent output; that's not optional just because the diff came from a tool instead of a person.</p>
</li>
</ul>
<h2>Starting Today</h2>
<p>If you haven't built this into your workflow yet, a reasonable pace looks like:</p>
<p><strong>Week 1  Try it yourself.</strong> Run Claude Code or Codex on a personal project. Start with investigation tasks only  no implementation  to build calibration for what "a good plan" looks like before you let it touch files.</p>
<p><strong>Weeks 24  Delegate in small steps.</strong> Hand off genuinely small, bounded tasks: adding tests, fixing type errors. Build prompt templates you trust. Build the habit of actually reading every diff, not skimming it.</p>
<p><strong>Month 2+  Roll out to the team.</strong> Maintain and share <code>AGENTS.md</code>/<code>CLAUDE.md</code>. Set up automated PR review. Share both the wins and the near-misses with your team  the failure stories are at least as instructive as the success stories.</p>
<h2>The Summary, If You Read Nothing Else</h2>
<p>AI agents aren't replacements for developers. They're development partners you can delegate discrete units of work to  research, implementation, testing, and review assistance  while you retain the judgment calls that actually carry risk.</p>
<p>Three things determine whether that delegation goes well:</p>
<ol>
<li><p><strong>Break work into small pieces.</strong> Large, vague requests are the root cause of most bad outcomes.</p>
</li>
<li><p><strong>Follow the full loop  investigate, plan, implement, test, review.</strong> Don't shortcut to implementation.</p>
</li>
<li><p><strong>AI does the work; humans hold the judgment and the responsibility.</strong> Design, security, and final decisions stay yours.</p>
</li>
</ol>
<p>The two skills that matter most going forward aren't really new skills at all  they're the ability to write genuinely clear instructions, and the ability to critically evaluate the output you get back. Both of those were always part of being a good engineer. The agents just made them the part that's visible.</p>
<hr />
<p><em>Further reading:</em> <a href="https://developers.openai.com/codex"><em>OpenAI Codex documentation</em></a><em>,</em> <a href="https://code.claude.com/docs"><em>Claude Code docs</em></a><em>,</em> <a href="https://claude.com/product/cowork"><em>Claude Cowork product page</em></a><em>.</em></p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-06-19-1822</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-06-19-1822</guid><category><![CDATA[AI]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[codex]]></category><category><![CDATA[claude]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Software Engineering for SQL: The Complete Guide to dbt Cloud at Scale]]></title><description><![CDATA[<h2>Introduction: The "T" Bottleneck in Modern Data Pipelines</h2>
<p>For years, the modern data stack has promised a seamless transition from raw, messy ingestion to beautiful, actionable business intelligence. We mastered the "E" (Extract) and the "L" (Load) using managed pipelines like Fivetran and Airbyte. However, as organizations scale, the "T" (Transform) remains a persistent bottleneck.</p>
<p>Without rigorous engineering practices, data warehouses quickly devolve into a chaotic "spaghetti" of untracked SQL scripts, scheduled by fragile cron jobs, and run with zero testing. Data engineers and analysts find themselves trapped in endless cycles of debugging, trying to figure out why downstream metrics are broken, and arguing over which table represents the actual "source of truth."</p>
<p>This is where <strong>dbt (data build tool)</strong> redefined the industry. By treating data transformation as a software engineering discipline, dbt brought version control, testing, documentation, and modularity to SQL [1]. But as data teams grow from a handful of analysts to hundreds of engineers across multiple business units, managing open-source <strong>dbt Core</strong> on self-hosted infrastructure introduces its own operational tax.</p>
<p>This comprehensive guide explores how <strong>dbt Cloud</strong> solves these enterprise-scale operational challenges, offering mid-to-senior engineers a robust, managed platform to execute the <strong>Analytics Development Lifecycle (ADLC)</strong> at scale [2].</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/dbt-cloud-a-complete-guide-analytics-engineering-at-scale">https://speakerdeck.com/x5gtrn/dbt-cloud-a-complete-guide-analytics-engineering-at-scale</a></p>

<hr />
<h2>1. The Analytics Development Lifecycle (ADLC)</h2>
<p>Software engineers have long relied on the Software Development Lifecycle (SDLC) to build, test, and deploy code reliably. The <strong>Analytics Development Lifecycle (ADLC)</strong> is dbts framework for bringing that same operational rigor to data assets [2].</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/c19ee987-3daa-46cc-be32-e96ca560d176.jpg" alt="" style="display:block;margin:0 auto" />

<p>The ADLC breaks down data transformation into five continuous phases:</p>
<ol>
<li><p><strong>Develop:</strong> Writing modular, version-controlled SQL or Python models.</p>
</li>
<li><p><strong>Test:</strong> Validating model logic and data quality before code hits production.</p>
</li>
<li><p><strong>Deploy:</strong> Automating orchestration and handling continuous deployment (CD).</p>
</li>
<li><p><strong>Observe:</strong> Proactively monitoring pipeline performance, runtimes, and failures.</p>
</li>
<li><p><strong>Discover:</strong> Enabling downstream stakeholders to find, understand, and trust data assets.</p>
</li>
</ol>
<p>While dbt Core provides the open-source compiler to execute models and tests locally, dbt Cloud provides the integrated SaaS infrastructure to manage the entire ADLC loop seamlessly under a single pane of glass [3].</p>
<hr />
<h2>2. dbt Core vs. dbt Cloud: The Operational Trade-Offs</h2>
<p>When evaluating whether to self-host dbt Core or adopt dbt Cloud, senior engineers must look beyond licensing costs and calculate the total cost of ownership (TCO).</p>
<table>
<thead>
<tr>
<th>Capability</th>
<th>dbt Core (Self-Hosted)</th>
<th>dbt Cloud (Managed Platform)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Execution &amp; Infra</strong></td>
<td>Local machines or self-managed VMs (e.g., Kubernetes, ECS).</td>
<td>Fully managed, auto-scaling serverless SaaS environment [3].</td>
</tr>
<tr>
<td><strong>Scheduling</strong></td>
<td>Requires external orchestrators (e.g., Apache Airflow, Prefect).</td>
<td>Out-of-the-box, declarative job scheduler [3].</td>
</tr>
<tr>
<td><strong>Development IDE</strong></td>
<td>Local editors (VS Code) with manual credentials management.</td>
<td>Browser-based Cloud IDE with zero-setup and instant onboarding [3].</td>
</tr>
<tr>
<td><strong>CI/CD Pipeline</strong></td>
<td>Custom CI scripts (GitHub Actions) with manual schema cleanup.</td>
<td>Native <strong>Slim CI</strong> and <strong>Merge Jobs</strong> for optimized differential testing [4].</td>
</tr>
<tr>
<td><strong>Lineage &amp; Catalog</strong></td>
<td>Static HTML docs hosted manually (e.g., on S3/GCS).</td>
<td><strong>dbt Explorer</strong> featuring interactive, real-time column-level lineage [5].</td>
</tr>
<tr>
<td><strong>Semantic Layer</strong></td>
<td>Not available natively.</td>
<td><strong>dbt Semantic Layer</strong> powered by MetricFlow for unified metric definitions [6].</td>
</tr>
<tr>
<td><strong>Team Federation</strong></td>
<td>Hard to govern; typically leads to monolithic repos.</td>
<td><strong>dbt Mesh</strong> for secure, multi-project domain-driven architectures [7].</td>
</tr>
</tbody></table>
<p>While dbt Core is an excellent choice for solo developers or small PoCs, scaling it across an enterprise requires dedicated DevOps resources to maintain Airflow integrations, build custom CI/CD pipelines, and secure local database credentials. dbt Cloud eliminates this operational overhead, allowing engineers to focus entirely on data modeling and quality.</p>
<hr />
<h2>3. Zero-Setup Development with Cloud IDE</h2>
<p>Onboarding new engineers to a local dbt Core environment can be notoriously slow. Setting up Python virtual environments, configuring database profiles (<code>profiles.yml</code>), managing Git SSH keys, and securing local credentials often takes days.</p>
<p>The <strong>dbt Cloud IDE</strong> solves this by providing a browser-based, containerized development environment that is pre-configured and ready on day one [3].</p>
<h3>Key Features of the Cloud IDE:</h3>
<ul>
<li><p><strong>Git-Native Workflows:</strong> Developers can create branches, commit code, open Pull Requests, and merge changes directly through the UI without running a single Git command in the terminal.</p>
</li>
<li><p><strong>Smart Autocomplete:</strong> The IDE parses your project's DAG in real-time, providing smart auto-completion for model names, column names, and Jinja macros.</p>
</li>
<li><p><strong>On-the-Fly Previews:</strong> Engineers can run a model and preview the actual data output (up to 10,000 rows) directly below their SQL code, eliminating the need to constantly switch back and forth between dbt and a database client.</p>
</li>
<li><p><strong>Linter Integration:</strong> Built-in <strong>SQLFluff</strong> automatically formats code and flags style violations on every save, ensuring a clean, unified codebase across the entire team [4].</p>
</li>
</ul>
<p>For engineers who still prefer their local setup, the <strong>dbt Cloud CLI</strong> allows developers to write code locally in VS Code (leveraging extensions like <em>dbt Power User</em>) while executing runs on dbt Cloud's managed infrastructure [4].</p>
<hr />
<h2>4. Slim CI: Smart Differential Testing</h2>
<p>In a mature data platform, a single Pull Request should never be merged without running tests. However, in large projects with hundreds or thousands of models, running <code>dbt build</code> on the entire DAG for every commit is incredibly slow and expensive.</p>
<p>dbt Cloud solves this with <strong>Slim CI</strong>, a native continuous integration feature that uses state comparison to run and test <em>only</em> what changed [4].</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/91d4398c-bc5f-48f0-861a-0ba4354bb994.jpg" alt="" style="display:block;margin:0 auto" />

<h3>How Slim CI Works Under the Hood:</h3>
<ol>
<li><p><strong>State Discovery:</strong> When a developer opens a Pull Request, dbt Cloud triggers a Slim CI job and fetches the metadata (<code>manifest.json</code>) from the latest successful production run [4].</p>
</li>
<li><p><strong>Differential Compilation:</strong> dbt compares the PR branch's code against the production manifest to identify modified models.</p>
</li>
<li><p><strong>Targeted Execution:</strong> Using the state selector method, dbt executes only the modified models and their immediate downstream dependencies in a temporary, isolated schema [4].</p>
</li>
<li><p><strong>Automated Testing:</strong> Data quality tests (e.g., uniqueness, referential integrity) are run only on these executed models.</p>
</li>
<li><p><strong>PR Feedback:</strong> dbt Cloud automatically posts a detailed status comment directly on the GitHub/GitLab PR, showing exactly which models passed or failed.</p>
</li>
</ol>
<h3>The Code Behind Slim CI</h3>
<p>Under the hood, dbt Cloud automatically appends specific selection flags to your CI commands:</p>
<pre><code class="language-bash"># Compile and run only modified models and their downstream dependencies,
# deferring unchanged upstream models to the production environment.
dbt build --select state:modified+ --defer --state prod_artifacts/
</code></pre>
<p>By deferring to production, dbt Cloud reads from existing production tables for any unchanged upstream dependencies, completely avoiding the need to rebuild them.</p>
<blockquote>
<p><strong>ROI Impact:</strong> In a real-world enterprise project with 500 models, modifying 3 models drops the CI runtime from <strong>45 minutes to just 3 minutes</strong>, saving thousands of dollars in warehouse compute costs [8].</p>
</blockquote>
<hr />
<h2>5. dbt Explorer: Interactive, Column-Level Lineage</h2>
<p>Static documentation is where data context goes to die. Traditional dbt documentation generated a static HTML site that quickly became outdated and failed to show how columns transformed across complex joins.</p>
<p><strong>dbt Explorer</strong> is dbt Clouds real-time, interactive metadata catalog [5]. It automatically maps your entire data estate, from raw source ingestion to final BI dashboard exposure.</p>
<h3>Key Capabilities:</h3>
<ul>
<li><p><strong>Column-Level Lineage (CLL):</strong> Drill down past table-level dependencies to trace exactly how a specific column (e.g., <code>gross_revenue</code>) is calculated, merged, and exposed downstream [5].</p>
</li>
<li><p><strong>Performance Analysis:</strong> Visualizes execution times and failure rates for every model, allowing senior engineers to instantly spot bottlenecks and optimize slow-running SQL.</p>
</li>
<li><p><strong>Project Recommendations:</strong> Proactively flags architectural issues, such as models missing tests, duplicate sources, or orphaned models that are no longer queried.</p>
</li>
</ul>
<p>If an executive flags that a metric in a Tableau dashboard looks incorrect, an engineer can use Column-Level Lineage to trace the column back through the DAG, find the exact model where the bug was introduced, and click <strong>"Open in IDE"</strong> to immediately fix the SQL code [5].</p>
<hr />
<h2>6. dbt Semantic Layer: Unified Metric Definitions</h2>
<p>One of the most common points of friction in modern organizations is metric discrepancy. The Finance team's Tableau dashboard shows one "monthly active user" count, while the Product team's Looker dashboard shows another. This happens because metric logic (e.g., exclusions, date truncations) is redefined inside each individual BI tool.</p>
<p>The <strong>dbt Semantic Layer</strong> (powered by MetricFlow) solves this by centralizing metric definitions directly inside your dbt code [6].</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/08c25519-be43-4f57-a251-edc859afda32.jpg" alt="" style="display:block;margin:0 auto" />

<p>Instead of writing custom SQL inside BI tools, you define your business metrics declaratively in YAML:</p>
<pre><code class="language-yaml"># models/metrics/revenue.yml
version: 2

metrics:
  - name: monthly_revenue
    label: Monthly Revenue
    description: "Sum of successful order amounts, excluding cancelled or refunded orders."
    type: sum
    type_params:
      measure: order_amount
    filter: |
      status NOT IN ('cancelled', 'refunded')
    time_grains: [day, week, month, quarter, year]
    dimensions:
      - region
      - product_category
</code></pre>
<h3>Why this is a Game Changer:</h3>
<ol>
<li><p><strong>Single Source of Truth:</strong> This YAML block is the <em>only</em> place where "monthly_revenue" is defined.</p>
</li>
<li><p><strong>Universal Integration:</strong> Major BI tools like Tableau, Looker, Google Sheets, and Hex connect directly to the dbt Semantic Layer [6].</p>
</li>
<li><p><strong>Dynamic SQL Generation:</strong> When a user requests "Revenue by Region last month" in Tableau, the Semantic Layer automatically compiles and executes the precise SQL on your warehouse, applying the correct filters and joins.</p>
</li>
</ol>
<hr />
<h2>7. dbt Mesh: Scaling to Federated Data Architectures</h2>
<p>As data teams grow, a monolithic dbt project inevitably becomes a bottleneck. Dozens of developers from different business units committing to a single repository leads to frequent merge conflicts, massive DAGs that are impossible to comprehend, and slow, bloated CI pipelines.</p>
<p><strong>dbt Mesh</strong> enables organizations to adopt a federated, domain-driven data mesh architecture by splitting a monolithic dbt project into smaller, interconnected projects [7].</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/385244c6-c29c-43a2-8e02-b2fdba72828e.jpg" alt="" style="display:block;margin:0 auto" />

<h3>Key Concepts of dbt Mesh:</h3>
<ul>
<li><p><strong>Domain-Specific Projects:</strong> Teams (e.g., Finance, Marketing, Product) maintain their own independent dbt repositories and deployment schedules [7].</p>
</li>
<li><p><strong>Model Access Control:</strong> Engineers can define access levels for their models:</p>
<ul>
<li><p><code>private</code>: Only accessible within the local project.</p>
</li>
<li><p><code>public</code>: Accessible by other dbt projects.</p>
</li>
</ul>
</li>
<li><p><strong>Cross-Project References:</strong> Downstream projects can safely reference public models from upstream projects using the standard <code>ref</code> function [7]:</p>
</li>
</ul>
<pre><code class="language-sql">-- Inside the Marketing dbt project
SELECT 
    customer_id,
    acquisition_channel,
    -- Safely referencing a public model from the Finance project
    {{ ref('finance_project', 'fct_revenue') }} as revenue
FROM {{ ref('stg_marketing_leads') }}
</code></pre>
<ul>
<li><strong>Cross-Project CI:</strong> If the Finance team opens a PR that modifies <code>fct_revenue</code>, dbt Clouds cross-project CI automatically triggers tests in the downstream Marketing project to ensure no downstream pipelines are broken before the change is merged [5].</li>
</ul>
<hr />
<h2>8. Real-World Business Impact and ROI</h2>
<p>Adopting dbt Cloud is not just an architectural upgrade; it delivers measurable business value to both engineering teams and business stakeholders.</p>
<p>According to research and customer case studies published by dbt Labs, organizations migrating from self-hosted dbt Core to dbt Cloud experience significant improvements across key operational metrics [8]:</p>
<ul>
<li><p><strong>40+ Hours Reclaimed Weekly:</strong> Data teams reclaim over an entire workweek of engineering time previously spent on managing infrastructure, debugging broken Airflow schedules, and manually deploying code [8].</p>
</li>
<li><p><strong>33% Fewer Incidents:</strong> Automated testing, native Slim CI guardrails, and column-level lineage prevent bad data from reaching production, resulting in a dramatic drop in data quality incidents [8].</p>
</li>
<li><p><strong>20% to 40% Compute Savings:</strong> By leveraging Slim CI to execute only modified models and utilizing declarative caching in the Semantic Layer, organizations significantly reduce their data warehouse compute spend [6] [8].</p>
</li>
</ul>
<hr />
<h2>Conclusion: The Path Forward</h2>
<p>For mid-to-senior engineers, dbt Cloud represents the natural evolution of the modern data stack. It shifts the focus from <strong>managing infrastructure</strong> to <strong>delivering high-quality, trusted data products</strong>.</p>
<p>By integrating the entire Analytics Development Lifecyclefrom zero-setup browser development and smart Slim CI testing to column-level lineage and federated domain managementdbt Cloud provides the robust, enterprise-grade foundation needed to scale analytics engineering with confidence.</p>
<p>If you are ready to transition your team from fragile, monolithic pipelines to a highly scalable, governed data platform, start by setting up a free dbt Cloud Developer account, connecting it to your cloud warehouse, and deploying your first automated Slim CI pipeline.</p>
<hr />
<h2>References</h2>
<p>[1] dbt Labs, <em>"Build trusted, scalable data pipelines with dbt,"</em> <a href="https://www.getdbt.com/product/dbt">getdbt.com/product/dbt</a>.<br />[2] dbt Labs, <em>"Creating reliable data products with analytics engineering,"</em> <a href="https://www.getdbt.com/blog/creating-reliable-data-products-with-analytics-engineering">getdbt.com/blog/creating-reliable-data-products-with-analytics-engineering</a>.<br />[3] Foundational, <em>"dbt Core vs dbt Cloud: Key Differences,"</em> <a href="https://www.foundational.io/blog/dbt-core-vs-dbt-cloud">foundational.io/blog/dbt-core-vs-dbt-cloud</a>.<br />[4] dbt Labs, <em>"What's new in dbt Cloud - June 2024,"</em> <a href="https://www.getdbt.com/blog/whats-new-in-dbt-cloud-june-2024">getdbt.com/blog/whats-new-in-dbt-cloud-june-2024</a>.<br />[5] dbt Labs, <em>"dbt Catalog helps you visualize and optimize data lineage,"</em> <a href="https://www.getdbt.com/product/dbt-catalog">getdbt.com/product/dbt-catalog</a>.<br />[6] dbt Labs, <em>"Delivering data that works: the biggest new dbt Cloud features,"</em> <a href="https://www.getdbt.com/blog/dbt-cloud-launch-showcase-2024">getdbt.com/blog/dbt-cloud-launch-showcase-2024</a>.<br />[7] dbt Labs, <em>"Adopting CI/CD with dbt Cloud,"</em> <a href="https://www.getdbt.com/blog/adopting-ci-cd-with-dbt-cloud">getdbt.com/blog/adopting-ci-cd-with-dbt-cloud</a>.<br />[8] dbt Labs, <em>"dbt platform vs Self-Hosting dbt,"</em> <a href="https://www.getdbt.com/product/self-hosting-dbt-vs-dbt-platform">getdbt.com/product/self-hosting-dbt-vs-dbt-platform</a>.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-05-27-1350</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-05-27-1350</guid><category><![CDATA[dbt]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[analytics engineering]]></category><category><![CDATA[SQL]]></category><category><![CDATA[dataops]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Snowflake Deep Dive: Architecture, Performance, and How It Compares to BigQuery & Redshift]]></title><description><![CDATA[<hr />
<p>As data volumes explode and the demand for real-time analytics grows, the choice of a cloud data warehouse (DWH) has become one of the most critical architectural decisions for engineering teams. While traditional on-premise solutions struggled with rigid scaling and resource contention, the cloud era introduced platforms that promised infinite elasticity. Among them, Snowflake has emerged as a dominant force since its founding in 2012, largely due to its innovative architecture that fundamentally rethought how storage and compute should interact.</p>
<p>In this deep dive, we will explore the inner workings of Snowflake's architecture, examine advanced features like Snowpark and Time Travel, and provide a definitive, engineer-focused comparison against its primary rivals: Google BigQuery and Amazon Redshift. Whether you are migrating from a legacy system or re-evaluating your current cloud stack, this guide will help you understand where Snowflake shines and where it might fall short.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/snowflake-the-complete-guide-to-cloud-data-platforms">https://speakerdeck.com/x5gtrn/snowflake-the-complete-guide-to-cloud-data-platforms</a></p>

<h2>The Paradigm Shift: Decoupling Storage and Compute</h2>
<p>To understand why Snowflake gained such rapid adoption, we must look at the problem it solved. Traditional data warehousesand even early cloud data warehousesoften relied on a shared-nothing architecture where storage and compute were tightly coupled within the same node. If you needed more storage, you had to buy more compute, and vice versa. Furthermore, concurrent queries from different teams (e.g., ETL jobs running alongside BI dashboards) would compete for the same CPU and memory resources, leading to degraded performance.</p>
<p>Snowflake introduced a hybrid architecture that combines the simplicity of shared-disk architectures with the performance of shared-nothing massively parallel processing (MPP) clusters [1]. This is realized through a distinct three-layer architecture.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/252b1d5f-d816-4f8e-998c-8624b6daa5a0.png" alt="" style="display:block;margin:0 auto" />

<h3>Layer 1: Database Storage</h3>
<p>At the foundation, Snowflake leverages cloud object storage (Amazon S3, Google Cloud Storage, or Azure Blob Storage) to persist data. When data is ingested, Snowflake automatically reorganizes it into its proprietary, optimized, compressed, columnar format.</p>
<p>Crucially, the data is divided into <strong>micro-partitions</strong>contiguous units of storage usually between 50 MB and 500 MB of uncompressed data. Snowflake automatically manages all metadata for these micro-partitions, including the min/max values of columns. This enables aggressive partition pruning during query execution. Instead of scanning entire tables, the query optimizer can skip micro-partitions that do not contain relevant data, drastically reducing I/O and improving query speed [1].</p>
<h3>Layer 2: Compute (Virtual Warehouses)</h3>
<p>The compute layer consists of "Virtual Warehouses." A virtual warehouse is an independent MPP compute cluster allocated from the cloud provider. Because storage is centralized and decoupled from compute, you can spin up multiple virtual warehouses that all access the same underlying data simultaneously without any contention.</p>
<p>For example, you can have an <code>X-Large</code> warehouse dedicated to heavy ETL transformations running at night, while a separate <code>Small</code> warehouse serves low-latency BI queries for the marketing team during the day. They do not share CPU or memory, ensuring perfect workload isolation. Virtual warehouses can scale up (resizing for more complex queries) or scale out (adding clusters to handle more concurrent users) in seconds, and you only pay for the compute credits you actually consume.</p>
<h3>Layer 3: Cloud Services</h3>
<p>The "brain" of Snowflake is the Cloud Services layer. This layer coordinates all activities across the platform. It handles authentication, infrastructure management, metadata management, query parsing, and optimization [1]. Because metadata is managed here, operations like table cloning or data sharing are essentially metadata operationsthey happen instantly and require zero data duplication.</p>
<h2>Beyond Standard SQL: Snowpark and Time Travel</h2>
<p>While a robust SQL engine is the table stakes for any DWH, Snowflake has expanded its capabilities to cater to data scientists and software engineers.</p>
<h3>Snowpark: Bringing Code to the Data</h3>
<p>Historically, performing complex machine learning or data transformations required extracting data from the DWH, processing it in an external environment (like an Apache Spark cluster), and loading the results back. This data movement is slow, expensive, and creates governance nightmares.</p>
<p>Snowpark solves this by allowing developers to write code in Python, Java, or Scala, which is then translated into SQL or executed in secure sandboxes directly within Snowflake's compute layer.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/f6979e6a-4ece-420a-8842-6a52a6493921.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-python"># Example: Using Snowpark Python to filter and aggregate data
from snowflake.snowpark import Session
import snowflake.snowpark.functions as F

# Create a session
session = Session.builder.configs(connection_parameters).create()

# Reference a table
df = session.table("sales_data")

# Perform DataFrame operations
# This code doesn't pull data to the local machine; 
# it pushes the computation down to the Snowflake warehouse.
high_value_sales = df.filter(F.col("amount") &gt; 1000)
summary = high_value_sales.group_by("region").agg(F.sum("amount").alias("total_sales"))

summary.show()
</code></pre>
<p>With Snowpark, data engineers can build complex data pipelines using familiar DataFrame APIs, and data scientists can deploy ML models for inference directly where the data lives.</p>
<h3>Time Travel and Fail-safe</h3>
<p>Accidental <code>DROP TABLE</code> or <code>UPDATE</code> statements without a <code>WHERE</code> clause are the stuff of nightmares for DBAs. Snowflake's Time Travel feature leverages its immutable micro-partition architecture to allow querying historical data.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/4ff495ca-f2fa-47d2-9341-9f787106642d.png" alt="" style="display:block;margin:0 auto" />

<p>By default, Snowflake retains 1 day of historical data, but Enterprise editions allow configuring this up to 90 days. You can query data exactly as it looked at a specific timestamp or before a specific query ID.</p>
<pre><code class="language-sql">-- Restore a table that was accidentally dropped
UNDROP TABLE critical_business_data;

-- Query data as it looked 2 hours ago
SELECT * FROM orders AT(OFFSET =&gt; -7200);

-- Query data before a specific bad transaction occurred
SELECT * FROM users BEFORE(STATEMENT =&gt; '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');
</code></pre>
<p>Beyond Time Travel, Snowflake maintains a 7-day "Fail-safe" period, which is non-configurable and accessible only by Snowflake support, providing a final safety net against catastrophic data loss.</p>
<h2>The Definitive Comparison: Snowflake vs. BigQuery vs. Redshift</h2>
<p>Choosing between Snowflake, Google BigQuery, and Amazon Redshift often comes down to your existing cloud ecosystem, pricing preferences, and operational philosophy. Let's break down how they compare across key engineering dimensions [2] [3].</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/411de471-9467-42e7-abc2-8aa670aba651.png" alt="" style="display:block;margin:0 auto" />

<h3>Architecture and Scaling</h3>
<ul>
<li><p><strong>Snowflake:</strong> Uses a decoupled architecture where you explicitly define virtual warehouses (compute clusters). Scaling up or down takes seconds. It provides granular control over workload isolation.</p>
</li>
<li><p><strong>BigQuery:</strong> A fully serverless, multi-tenant architecture. You do not provision nodes or clusters; Google handles resource allocation under the hood. It can scale to thousands of cores instantly for a single query.</p>
</li>
<li><p><strong>Redshift:</strong> Traditionally a provisioned cluster model. While the newer RA3 nodes separate compute and managed storage, scaling operations (like resizing a cluster) historically took longer, though features like Concurrency Scaling have improved this. It requires more hands-on tuning (e.g., vacuuming, distribution keys) compared to the others.</p>
</li>
</ul>
<h3>Pricing Models</h3>
<ul>
<li><p><strong>Snowflake:</strong> You pay for storage (usually a flat rate per TB) and compute (measured in "credits" based on the size of the virtual warehouse and how long it runs). If the warehouse suspends after 1 minute of inactivity, you stop paying for compute.</p>
</li>
<li><p><strong>BigQuery:</strong> Offers two main models. On-demand pricing charges per terabyte of data scanned by your queries ($6.25/TB), which is great for unpredictable workloads but requires strict query optimization to avoid bill shock. Alternatively, flat-rate (capacity) pricing provides predictable costs for enterprise workloads [2].</p>
</li>
<li><p><strong>Redshift:</strong> Charges based on the instance types and hours they run. It is highly cost-effective if you commit to 1-year or 3-year Reserved Instances (up to 75% discount) and have consistent, 24/7 workloads.</p>
</li>
</ul>
<h3>Data Types and Ecosystem</h3>
<ul>
<li><p><strong>Snowflake:</strong> Natively supports semi-structured data (JSON, Avro, Parquet) via the <code>VARIANT</code> data type, allowing you to query JSON as easily as relational columns. Its multi-cloud nature (running on AWS, Azure, or GCP) prevents vendor lock-in. The Snowflake Marketplace is also a massive advantage for sharing and acquiring third-party data.</p>
</li>
<li><p><strong>BigQuery:</strong> Excellent support for nested and repeated fields. It shines if your company is deeply embedded in the Google Cloud ecosystem (e.g., using Google Analytics, Looker, or Vertex AI).</p>
</li>
<li><p><strong>Redshift:</strong> Best suited for teams fully committed to AWS. It integrates seamlessly with AWS services like S3 (via Redshift Spectrum), AWS Glue, and SageMaker.</p>
</li>
</ul>
<h2>When to Choose Snowflake</h2>
<p>Based on the architectural differences, Snowflake is typically the best choice in the following scenarios:</p>
<ol>
<li><p><strong>Multi-Cloud Strategy:</strong> If your organization operates across AWS and Azure, or wants to avoid vendor lock-in, Snowflake provides a consistent experience across all major clouds.</p>
</li>
<li><p><strong>Extreme Workload Isolation:</strong> If you have distinct teams (Data Engineering, BI, Data Science) that frequently clash over database resources, Snowflake's ability to spin up isolated virtual warehouses against the same data is unparalleled.</p>
</li>
<li><p><strong>Data Sharing and Monetization:</strong> If your business model involves sharing live data with clients, partners, or vendors, Snowflake's Secure Data Sharing allows this without copying or moving data.</p>
</li>
<li><p><strong>Minimal Administration:</strong> If your engineering team wants to focus on building pipelines rather than tuning distribution keys, managing indexes, or vacuuming tables, Snowflake's "near-zero maintenance" philosophy pays massive dividends.</p>
</li>
</ol>
<h2>Conclusion</h2>
<p>The cloud data warehouse landscape is fiercely competitive, but Snowflake has carved out a massive share of the market by solving the hardest problems of the on-premise era: resource contention, administrative overhead, and rigid scaling. While BigQuery remains a powerhouse for serverless, ad-hoc analysis on GCP, and Redshift provides deep value for AWS-native shops, Snowflake's decoupled architecture, multi-cloud flexibility, and developer-friendly features like Snowpark make it the platform of choice for many modern data engineering teams.</p>
<p>Ultimately, "Data is the oil of the 21st century, and Snowflake is the refinery." Choosing the right refinery depends on the pipelines you've already built, but Snowflake's design ensures that as your data volume and complexity grow, your infrastructure won't be the bottleneck.</p>
<hr />
<h3>References</h3>
<p>[1] Snowflake Documentation: Key Concepts and Architecture. <a href="https://docs.snowflake.com/en/user-guide/intro-key-concepts">https://docs.snowflake.com/en/user-guide/intro-key-concepts</a></p>
<p>[2] Snowflake vs Redshift vs BigQuery : The truth about pricing. <a href="https://www.reddit.com/r/dataengineering/comments/1hpfwuo/snowflake_vs_redshift_vs_bigquery_the_truth_about/">https://www.reddit.com/r/dataengineering/comments/1hpfwuo/snowflake_vs_redshift_vs_bigquery_the_truth_about/</a></p>
<p>[3] Cloud Data Warehouse Comparison: Redshift vs BigQuery vs Azure vs Snowflake.<br /><a href="https://www.striim.com/blog/cloud-data-warehouse-comparison-redshift-vs-bigquery-vs-azure-vs-snowflake-for-real-time-data">https://www.striim.com/blog/cloud-data-warehouse-comparison-redshift-vs-bigquery-vs-azure-vs-snowflake-for-real-time-data</a></p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-05-25-1132</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-05-25-1132</guid><category><![CDATA[data-engineering]]></category><category><![CDATA[snowflake]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[The Ultimate Freelance Platform Guide for IT Engineers: Maximizing Your Global Earning Potential]]></title><description><![CDATA[<p>The landscape of software engineering has fundamentally shifted. Gone are the days when your earning potential was strictly bound by your geographic location or the local tech market's salary ceilings. Today, the global freelance market presents an unprecedented opportunity for IT engineers to access high-paying projects, collaborate with cutting-edge startups, and achieve true location independence. The global freelance market is projected to reach staggering heights, and for engineers with the right skills and English proficiency, overseas projects often offer compensation that is three to ten times higher than domestic rates.</p>
<p>However, stepping into the international freelance arena can be daunting. With dozens of platforms available, each boasting different fee structures, vetting processes, and client bases, choosing the right starting point is critical. A misstep could mean weeks wasted on low-quality proposals or losing a significant chunk of your hard-earned money to hidden fees.</p>
<p>This comprehensive guide provides a deep, multi-angle comparison of six leading freelance platforms: <a href="https://upwork.com">Upwork</a>, <a href="https://www.guru.com">Guru</a>, <a href="https://weworkremotely.com">We Work Remotely</a>, <a href="https://gun.io">Gun.io</a>, <a href="https://www.peopleperhour.com">PeoplePerHour</a>, and <a href="https://arc.dev">Arc.dev</a>. Whether you are a beginner looking to build your first track record or a senior developer aiming to maximize your income with zero commission fees, this article will equip you with the knowledge to make an informed, strategic decision.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/freelance-platform-comparison-for-it-engineers">https://speakerdeck.com/x5gtrn/freelance-platform-comparison-for-it-engineers</a></p>

<h2>Why Target the Global Freelance Market?</h2>
<p>Before diving into the platform specifics, it is essential to understand why the global market is worth your time and effort. The transition from a traditional employment model to global freelancing is not just a lifestyle choice; it is a strategic career move.</p>
<p>First, the sheer scale of the market is immense. Companies worldwide, particularly in North America and Europe, are facing severe talent shortages in specialized tech roles. They are increasingly turning to global talent pools to fill these gaps. This demand drives up rates, allowing engineers in regions with lower costs of living to earn Silicon Valley-level compensation.</p>
<p>Second, the adoption of remote work has normalized asynchronous communication and distributed team structures. You no longer need to be in the same time zone to be an integral part of a development team. English proficiency is the primary bridge; if you can communicate technical concepts clearly in English, you can contract directly with companies anywhere in the world.</p>
<p>Finally, freelancing offers unparalleled flexibility. You can choose projects that align with your technical interests, whether that means building scalable backends in Go, crafting responsive frontends with React, or architecting complex cloud infrastructure on AWS. You are in control of your tech stack, your hours, and your career trajectory.</p>
<h2>The 6 Platforms at a Glance</h2>
<p>To help you navigate this ecosystem, we have categorized six major platforms based on their target audience, skill level requirements, and operational models.</p>
<ol>
<li><p><strong>Upwork</strong>: The world's largest comprehensive freelance marketplace, suitable for everyone from beginners to advanced professionals.</p>
</li>
<li><p><strong>Guru</strong>: A trusted legacy platform known for its robust SafePay protection, also catering to a wide range of skill levels.</p>
</li>
<li><p><strong>We Work Remotely</strong>: The leading remote-only job board, ideal for intermediate to advanced engineers seeking full-time or long-term contracts.</p>
</li>
<li><p><strong>Gun.io</strong>: An elite, heavily vetted platform exclusively for senior developers targeting high-paying projects.</p>
</li>
<li><p><strong>PeoplePerHour</strong>: A UK-based platform that allows you to sell your skills as fixed-price packages, suitable for all levels.</p>
</li>
<li><p><strong>Arc.dev</strong>: A premium platform with Silicon Valley-standard vetting, offering a 0% fee structure for top-tier talent.</p>
</li>
</ol>
<p>Let us break down each platform in detail.</p>
<hr />
<h2>1. Upwork: The World's Largest Marketplace</h2>
<p><a href="https://upwork.com">Upwork</a> is arguably the most recognized name in the freelance industry. Formed from the merger of Elance and oDesk, it boasts over 18 million registered freelancers across more than 180 countries.</p>
<h3>Key Features and Ecosystem</h3>
<p>Upwork's greatest strength is its sheer volume of opportunities. Whether you are looking for a quick bug fix project or a multi-month enterprise software development contract, you will find it here. The platform supports both hourly and fixed-price contracts, providing flexibility in how you structure your engagements.</p>
<p>For IT engineers, Upwork offers a robust environment. It features an "Expert-Vetted" certification for top-tier talent, which can significantly boost your visibility to enterprise clients. Furthermore, Upwork has recently integrated AI-powered hiring assistance tools to help match freelancers with relevant projects more efficiently.</p>
<h3>Payment Protection</h3>
<p>Safety is a major concern for freelancers, and Upwork addresses this with its comprehensive payment protection systems. For hourly contracts, the "Work Diary" application tracks your time, keystrokes, and takes periodic screenshots, guaranteeing payment for hours logged. For fixed-price contracts, funds are held in escrow and released upon the completion of predefined milestones.</p>
<h3>Fee Structure</h3>
<p>Upwork operates on a sliding scale fee structure that rewards long-term client relationships. The fee is 10% on all earnings. <em>(Note: Upwork recently updated its fee structure to a flat 10% for freelancers, moving away from the previous 20%/10%/5% sliding scale, though legacy contracts may have different terms. Always check the latest official documentation).</em></p>
<p><strong>Best For:</strong> Engineers looking to build a track record from scratch and secure a steady stream of diverse projects. It is the perfect training ground for mastering client communication and proposal writing.</p>
<blockquote>
<p>If you are a senior Japanese engineer looking for a step-by-step walkthrough of Upwork  from profile setup to landing your first contract  check out this in-depth practical guide: <a href="https://daisuke.masuda.tokyo/article-2026-04-29-0155">Breaking the 'Zero Experience' Barrier: A Practical Upwork Guide for Senior Japanese Engineers</a>.</p>
</blockquote>
<hr />
<h2>2. Guru: The Trusted Legacy Platform</h2>
<p>Founded in 1998, <a href="https://www.guru.com">Guru</a> is one of the oldest freelance platforms on the internet. With over 25 years of proven track record and more than 800,000 registered employers worldwide, it has facilitated over $250 million in payments.</p>
<h3>Key Features and Ecosystem</h3>
<p>Guru distinguishes itself with a straightforward, no-nonsense approach to freelancing. It provides a feature called "WorkRooms," which serves as a centralized hub for project management, communication, and file sharing between you and the client. This built-in infrastructure can be particularly useful for managing complex IT projects without needing external tools.</p>
<h3>Payment Protection</h3>
<p>Guru's standout feature is "SafePay." Before you begin any work, the client is required to fund the SafePay escrow account. This ensures that the funds are available and committed before you write a single line of code. Withdrawals are flexible, supporting PayPal, Payoneer, and direct wire transfers.</p>
<h3>Fee Structure</h3>
<p>Guru's fee structure is tied to its membership tiers. Basic (free) members pay a 9% job fee, while paid membership tiers (ranging from \(11.95 to \)49.95 per month) reduce this fee down to 5%. Paid memberships also provide more "Bids" (the currency used to apply for jobs) and increased visibility.</p>
<p><strong>Best For:</strong> Engineers who prioritize secure payments and prefer a stable, traditional platform environment. It is an excellent alternative or supplement to Upwork for diversifying your client acquisition channels.</p>
<hr />
<h2>3. We Work Remotely: The Remote-Only Job Board</h2>
<p><a href="https://weworkremotely.com">We Work Remotely (WWR)</a> operates on a fundamentally different model than Upwork or Guru. Founded in 2013, it is not a freelance marketplace where you bid on micro-tasks; rather, it is the leading remote-only job board.</p>
<h3>Key Features and Ecosystem</h3>
<p>WWR features listings exclusively from remote-first companies. It is a goldmine for roles in Software Development, Data Engineering, DevOps, and Product Management. The platform attracts over 6 million monthly visitors and is utilized by top tech companies looking to hire globally distributed teams.</p>
<p>Because it is a job board, the engagement model is direct. You apply for a position, go through the company's interview process, and if hired, you sign a contract directly with them. This often results in long-term contracting or full-time remote employment.</p>
<h3>Payment Protection</h3>
<p>Since WWR only facilitates the connection, payment protection depends entirely on the hiring company's policies and the contract you sign. There is no built-in escrow system. You must conduct your own due diligence on the employer.</p>
<h3>Fee Structure</h3>
<p>The best part about WWR for engineers is that it is completely free. There are <strong>0% fees</strong> for job seekers. The platform monetizes by charging employers $299 per job post, which naturally filters out low-quality clients and ensures that only serious companies are hiring.</p>
<p><strong>Best For:</strong> Mid-to-senior engineers seeking full-time remote roles, stable long-term contracts, and direct integration into a company's core team without platform intermediaries.</p>
<hr />
<h2>4. Gun.io: The Elite Developer Platform</h2>
<p>If you are a senior engineer with a decade of experience, competing on general marketplaces can feel like a race to the bottom. <a href="https://gun.io">Gun.io</a> solves this by creating an exclusive, highly vetted environment.</p>
<h3>Key Features and Ecosystem</h3>
<p>Gun.io is strictly for elite developers. They maintain a rigorous technical vetting process with an acceptance rate of approximately 10%. The evaluation includes coding tests and live technical interviews conducted by senior engineers.</p>
<p>Because the talent pool is curated, the clients are too. Gun.io focuses on high-paying projects, typically ranging from \(100 to \)200+ per hour. They support a wide array of modern tech stacks, including Java, Python, JavaScript, React, and Node.js.</p>
<h3>Payment Protection</h3>
<p>Gun.io handles all the billing and invoicing. They offer weekly payouts and support multi-currency transfers to over 100 countries. This ensures that you get paid reliably and on time, without having to chase clients for invoices.</p>
<h3>Fee Structure</h3>
<p>Unlike platforms that take a percentage of your stated rate, Gun.io's fee is included in the rate presented to the client. You set your desired take-home hourly rate, and Gun.io adds their margin on top when billing the client. What you ask for is exactly what you get.</p>
<p><strong>Best For:</strong> Senior engineers (10+ years of experience) who want to bypass the bidding wars and focus exclusively on high-paying, high-quality projects with premium clients.</p>
<hr />
<h2>5. PeoplePerHour: Productize Your Skills</h2>
<p><a href="https://www.peopleperhour.com">PeoplePerHour (PPH)</a> is a UK-based platform founded in 2007 that has grown to serve over 3 million freelancers across 100+ countries. It offers a unique approach to freelancing that blends traditional bidding with productized services.</p>
<h3>Key Features and Ecosystem</h3>
<p>While you can bid on custom projects, PPH's standout feature is "Hourlies." An Hourlie allows you to package your skills into a fixed-price service with clear deliverables. For example, instead of bidding on a general "web development" job, you can create an Hourlie titled "I will build a responsive React landing page in 3 days for $500."</p>
<p>This productized approach allows for passive project acquisition. Clients can browse Hourlies and purchase them directly, much like buying a product on an e-commerce site. PPH also utilizes an AI-powered matching system to connect freelancers with relevant client requests. Furthermore, all freelancers are manually reviewed and approved before they can start selling, maintaining a baseline of quality.</p>
<h3>Payment Protection</h3>
<p>PPH utilizes a robust escrow system. Clients must deposit funds into the escrow account before you begin working on an Hourlie or a custom project. Once the work is delivered and approved, the funds are released. Withdrawals can be made via credit cards, PayPal, and bank transfers.</p>
<h3>Fee Structure</h3>
<p>PPH uses a sliding scale fee structure based on your lifetime billing with a specific buyer. The fee starts at 20% for the first 250 (or equivalent) billed to a client, drops to 7.5% for earnings between 250 and 5,000, and falls to 3.5% for anything over 5,000. This heavily incentivizes building long-term relationships with clients.</p>
<p><strong>Best For:</strong> Engineers who want to productize their specific skills (e.g., API integrations, specific CMS setups, code audits) and acquire projects passively without constantly writing custom proposals.</p>
<hr />
<h2>6. Arc.dev: Silicon Valley Standards, Zero Fees</h2>
<p><a href="https://arc.dev">Arc.dev</a> represents the pinnacle of the freelance platform evolution for top-tier talent. It is designed to connect the world's best developers directly with US startups and tech companies.</p>
<h3>Key Features and Ecosystem</h3>
<p>Arc.dev is incredibly exclusive. It employs a Silicon Valley-standard vetting process, resulting in an acceptance rate of only the top 2-3% of applicants. The rigorous evaluation includes pair programming interviews and comprehensive system design assessments.</p>
<p>Once you pass the vetting, you gain access to a network of over 450,000 registered talents across 190 countries and, more importantly, direct matching with premium clients who understand the value of top engineering talent.</p>
<h3>Payment Protection</h3>
<p>Arc.dev partners with Employer of Record (EOR) services to handle compliance, contracts, and payments. This ensures a highly secure payment pipeline. They support various withdrawal methods, including ACH, Wise, PayPal, and even Bitcoin in some cases.</p>
<h3>Fee Structure</h3>
<p>The most compelling reason to strive for Arc.dev is its fee structure: <strong>0% commission fee for freelancers</strong>. It is the industry's lowest. The platform generates its revenue entirely by charging the clients. You keep 100% of your negotiated rate.</p>
<p><strong>Best For:</strong> Top-tier engineers who possess exceptional technical and communication skills, aiming to maximize their income by eliminating platform fees entirely.</p>
<hr />
<h2>Comparative Analysis: Making the Data-Driven Choice</h2>
<p>To synthesize this information, let us look at the data across three critical dimensions: Fees, Vetting Difficulty, and Payment Safety.</p>
<h3>1. The Impact of Fees on Your Bottom Line</h3>
<p>Fee structures directly impact your take-home pay. While a 10% fee might seem small initially, over a \(50,000 contract, that is \)5,000 lost to the platform.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/92a8fa65-b1f6-4db4-b2ee-12392a8d7bab.jpg" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Upwork:</strong> Flat 10% (historically sliding scale).</p>
</li>
<li><p><strong>Guru:</strong> 5-9% depending on your paid membership tier.</p>
</li>
<li><p><strong>We Work Remotely:</strong> 0% (Direct hire).</p>
</li>
<li><p><strong>Gun.io:</strong> 0% deducted from your rate (Platform adds margin on top).</p>
</li>
<li><p><strong>PeoplePerHour:</strong> 20% -&gt; 7.5% -&gt; 3.5% (Sliding scale based on lifetime client billing).</p>
</li>
<li><p><strong>Arc.dev:</strong> 0% (Client pays all fees).</p>
</li>
</ul>
<p><strong>Insight:</strong> If you are playing the long game, platforms with 0% freelancer fees (WWR, Arc.dev) or those that add their margin on top (Gun.io) offer the highest absolute earning potential. However, these platforms also have the highest barriers to entry.</p>
<h3>2. Vetting Difficulty vs. Earning Potential</h3>
<p>There is a direct correlation between how hard it is to get onto a platform and how much you can earn once you are there.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/c445e1a5-5dcd-4228-86ad-f7ffe1640b85.jpg" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Easy Entry (Upwork, Guru):</strong> Anyone can create a profile. The competition is fierce, and you will often compete on price initially. However, the volume of jobs is massive.</p>
</li>
<li><p><strong>Moderate Entry (WWR, PeoplePerHour):</strong> WWR requires passing the hiring company's specific interview process. PPH requires a manual profile review. The competition is slightly filtered.</p>
</li>
<li><p><strong>Hard Entry (Gun.io, Arc.dev):</strong> Requires passing rigorous technical interviews and system design tests. Acceptance rates are below 10%. However, once inside, you compete only with other elite developers for premium rates.</p>
</li>
</ul>
<p><strong>Insight:</strong> Beginners should start on Upwork or Guru to build a portfolio and learn client management. As your skills mature, you should actively attempt to migrate to WWR, Gun.io, or Arc.dev to escape the race to the bottom.</p>
<h3>3. Payment Protection and Safety</h3>
<p>Unpaid invoices are the bane of freelancing. Understanding how a platform protects your money is crucial.</p>
<table>
<thead>
<tr>
<th>Platform</th>
<th>Protection Mechanism</th>
<th>Escrow</th>
<th>Safety Rating</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Upwork</strong></td>
<td>Work Diary (Hourly) + Milestones (Fixed)</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>Guru</strong></td>
<td>SafePay (Pre-funded before work starts)</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>Arc.dev</strong></td>
<td>Handled via EOR Partners</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>Gun.io</strong></td>
<td>Weekly Payouts managed by platform</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>PeoplePerHour</strong></td>
<td>Escrow System</td>
<td>Yes</td>
<td></td>
</tr>
<tr>
<td><strong>We Work Remotely</strong></td>
<td>Depends entirely on the hiring company</td>
<td>No</td>
<td></td>
</tr>
</tbody></table>
<p><strong>Insight:</strong> Marketplaces (Upwork, Guru, PPH) excel at protecting micro-transactions and short-term contracts via escrow. For direct-hire boards like WWR, you must act as your own legal and financial advocate.</p>
<hr />
<h2>Practical Tips for Success in the Global Market</h2>
<p>Choosing the right platform is only the first step. Your success depends heavily on execution. Here are actionable strategies to elevate your freelance career.</p>
<h3>1. Profile Optimization is Non-Negotiable</h3>
<p>Your profile is your storefront. A generic "I am a Java developer" will not cut it.</p>
<ul>
<li><p><strong>Quantify Your Impact:</strong> Instead of saying "Improved database performance," write "Optimized PostgreSQL queries, reducing API response time by 40% and saving $500/month in AWS costs."</p>
</li>
<li><p><strong>Show, Don't Just Tell:</strong> Always link to a well-maintained GitHub profile, live projects, or a personal portfolio site. Code quality speaks louder than self-proclaimed expertise.</p>
</li>
<li><p><strong>Niche Down:</strong> Generalists compete on price; specialists compete on value. Position yourself as an expert in a specific domain (e.g., "React Native Developer for FinTech Startups" rather than just "Mobile Developer"). For a detailed breakdown of how to craft a compelling Upwork profile title and overview  including real examples for Japanese engineers  see <a href="https://daisuke.masuda.tokyo/article-2026-04-29-0155">this comprehensive Upwork guide</a>.</p>
</li>
</ul>
<h3>2. Master the Art of the Proposal</h3>
<p>Clients on platforms like Upwork receive dozens of proposals within minutes. You must stand out immediately.</p>
<ul>
<li><p><strong>Address the Core Problem:</strong> Do not copy-paste templates. Read the job description carefully and start your proposal by addressing their specific pain point.</p>
</li>
<li><p><strong>Propose a Solution:</strong> Briefly outline <em>how</em> you will solve their problem. This demonstrates competence before you are even hired.</p>
</li>
<li><p><strong>The "Loss Leader" Strategy:</strong> When starting on a new platform, consider taking your first 2-3 jobs at a slightly lower rate. Your primary goal is to secure 5-star reviews. Once you have social proof, you can rapidly increase your rates.</p>
</li>
</ul>
<h3>3. Adopt a Long-Term Strategy</h3>
<p>Freelancing is a business; treat it like one.</p>
<ul>
<li><p><strong>Diversify Your Channels:</strong> Do not rely solely on one platform. Maintain an active presence on Upwork while applying for roles on WWR or preparing for the Arc.dev interview.</p>
</li>
<li><p><strong>Transition to Long-Term Contracts:</strong> Constantly hunting for new clients is exhausting. Aim to convert successful short-term projects into ongoing retainer agreements.</p>
</li>
<li><p><strong>Continuous Rate Increases:</strong> Every time you complete a successful project or acquire a new certification, evaluate your hourly rate. You should be consistently pushing your rates upward as your value increases.</p>
</li>
</ul>
<hr />
<h2>Conclusion: Your Next Steps</h2>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/c7c784ec-912f-4ddd-b886-ec8910f974bc.jpg" alt="" style="display:block;margin:0 auto" />

<p>Entering the global freelance market is a transformative career move. It requires technical excellence, strong communication skills, and strategic platform selection.</p>
<p>Here is your concrete action plan:</p>
<ol>
<li><p><strong>If you are starting out:</strong> Register on <strong>Upwork</strong> and <strong>Guru</strong> today. Spend the weekend optimizing your profile and writing your first five highly targeted proposals. Focus on getting your first 5-star review.</p>
</li>
<li><p><strong>If you want to productize:</strong> Create an account on <strong>PeoplePerHour</strong> and design three "Hourlies" based on tasks you can execute quickly and flawlessly.</p>
</li>
<li><p><strong>If you want stability:</strong> Bookmark <strong>We Work Remotely</strong> and set up alerts for your specific tech stack. Treat these applications like traditional job hunts.</p>
</li>
<li><p><strong>If you are a senior engineer:</strong> Begin preparing for technical interviews. Review system design concepts and algorithms, then apply to <strong>Gun.io</strong> or <strong>Arc.dev</strong> to unlock the highest earning tiers.</p>
</li>
</ol>
<p>The global market is waiting. By understanding the nuances of these platforms and strategically positioning your skills, you can take control of your career, maximize your income, and achieve true professional freedom. The first step is simply deciding to start.</p>
<hr />
<p><em>References:</em></p>
<ul>
<li><p>[1] <a href="https://upwork.com">Upwork Official Website</a></p>
</li>
<li><p>[2] <a href="https://www.guru.com">Guru Official Website</a></p>
</li>
<li><p>[3] <a href="https://weworkremotely.com">We Work Remotely Official Website</a></p>
</li>
<li><p>[4] <a href="https://gun.io">Gun.io Official Website</a></p>
</li>
<li><p>[5] <a href="https://www.peopleperhour.com">PeoplePerHour Official Website</a></p>
</li>
<li><p>[6] <a href="https://arc.dev">Arc.dev Official Website</a></p>
</li>
</ul>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-04-30-0608</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-04-30-0608</guid><category><![CDATA[freelance]]></category><category><![CDATA[software development]]></category><category><![CDATA[remote work]]></category><category><![CDATA[career advice]]></category><category><![CDATA[tech ]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Breaking the 'Zero Experience' Barrier: A Practical Upwork Guide for Senior Japanese Engineers]]></title><description><![CDATA[<p>For many Japanese IT engineers with decades of experience, the idea of entering the global freelance market feels like starting from scratch. You might have architected enterprise systems, led development teams across multiple projects, and mastered complex tech stacks spanning multiple generations of technology. Yet when you create an account on <a href="https://www.upwork.com/">Upwork</a>, the world's largest freelance platform with over 18 million registered freelancers, you are immediately faced with a harsh reality: you have zero platform history.</p>
<p>This "zero experience" barrier is the single biggest hurdle for senior professionals transitioning to global freelancing. Clients on Upwork rely heavily on platform-specific reviews and a metric called the Job Success Score (JSS) to make hiring decisions. No matter how impressive your local resume is  20 years of enterprise Java development, a portfolio of production systems serving millions of users, or deep expertise in cloud infrastructure  without Upwork reviews, you are an unknown entity in a crowded marketplace.</p>
<p>Furthermore, many Japanese engineers hesitate to take the leap due to anxiety about their English proficiency. The fear of being unable to communicate technical nuances, negotiate contracts, or handle client complaints in a foreign language is real and understandable. However, as we will explore in detail throughout this guide, that fear is largely unfounded for the type of work that experienced engineers do.</p>
<p>This guide is designed specifically for experienced IT engineers with intermediate English skills who are ready to enter the global freelance market. We will cover every step of the journey: setting up a compelling profile, understanding Upwork's unique mechanics, writing proposals that win contracts, pricing your services strategically, protecting your reputation, managing withdrawals and taxes as a Japanese resident, and following a concrete 4-week action plan to land that crucial first job. Let us begin.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/practical-guide-to-landing-your-first-job-on-upwork">https://speakerdeck.com/x5gtrn/practical-guide-to-landing-your-first-job-on-upwork</a></p>

<hr />
<h2>Understanding the Upwork Ecosystem</h2>
<p>Before diving into tactics, it is worth understanding what makes Upwork different from other freelance platforms and from the Japanese domestic market.</p>
<p><a href="https://www.upwork.com/">Upwork</a> is a two-sided marketplace where clients post jobs and freelancers submit proposals. Unlike Japanese platforms such as Lancers or Crowdworks, Upwork is a global market with clients primarily from the United States, Western Europe, and Australia. The average hourly rates are significantly higher  a senior backend developer can realistically earn USD 80  USD 150/hr once established  but the competition is also global, with strong competition from developers in Eastern Europe, India, and Southeast Asia.</p>
<p>The platform operates on a reputation economy. Every completed contract generates a review and contributes to your JSS. Clients filter candidates by JSS, badge status, and hourly rate. This means that in the early stages, you are not just competing on skill  you are competing on trust signals that you have not yet had the chance to build.</p>
<h3>Key Upwork Mechanics You Must Understand</h3>
<p><strong>Connects</strong> are Upwork's virtual currency for submitting proposals. Each proposal costs between 2 and 16 Connects depending on the job's budget. You receive a limited number of free Connects each month, and additional ones must be purchased. This creates a natural incentive to be selective: do not spray proposals randomly. Every Connect spent should be a deliberate investment.</p>
<p><strong>The Job Success Score (JSS)</strong> is a rolling metric that reflects your overall client satisfaction over the past 24 months. It is calculated based on completed contracts, client feedback (both public reviews and private feedback), long-term client relationships, and the absence of disputes or cancellations. A JSS of 90% or above qualifies you for the "Top Rated" badge, which dramatically increases your visibility in search results and gives you access to a special feature called "Top Rated Protection" that allows you to remove one negative review per year.</p>
<p><strong>Service Fees</strong> are charged by Upwork as a percentage of your earnings., the fee is 20% for the first USD 500 billed to a client, 10% for billings between USD 500.01 and USD 10,000, and 5% for billings over USD 10,000 with the same client. This means that building long-term relationships with clients is financially advantageous, as your effective fee rate decreases over time.</p>
<p><strong>Badges</strong> are public trust signals displayed on your profile. The "Rising Talent" badge is awarded to new freelancers who show strong early performance. "Top Rated" requires a JSS of 90%+ and a minimum earnings threshold. "Top Rated Plus" is the highest tier, requiring a JSS of 90%+ and significant earnings. These badges are not just cosmetic  they directly affect how often your profile appears in client searches.</p>
<hr />
<h2>The Reality of English on Upwork</h2>
<p>Let us address the elephant in the room first: English anxiety. Many Japanese engineers believe they need near-native fluency to succeed in the global market. This assumption leads to paralysis, and it is largely unfounded for technical freelancing roles.</p>
<p>Consider the nature of the work. When you are building a REST API, optimizing a database schema, or setting up a CI/CD pipeline, the deliverable is code and documentation  not conversation. The vast majority of client communication on Upwork happens through the platform's messaging system, which is text-based and asynchronous. You have time to compose your messages carefully, use translation tools, and review your writing before sending. Video calls are far less common than in corporate environments, and when they do occur, they are typically short, structured technical discussions rather than open-ended conversations.</p>
<p>Clients on Upwork value two things above all else: <strong>understanding of requirements</strong> and <strong>response speed</strong>. A freelancer who writes simple, clear English and responds within 24 hours will consistently outperform a native English speaker who is vague, slow to reply, or unclear about technical requirements. In fact, many experienced clients prefer working with non-native speakers who communicate with precision and directness, because it reduces ambiguity.</p>
<h3>Your Practical English Toolkit</h3>
<p>You do not need to improve your English before starting on Upwork. You need to use the right tools to communicate effectively right now.</p>
<p><a href="https://www.deepl.com/"><strong>DeepL</strong></a> is the gold standard for Japanese-to-English translation, producing far more natural results than Google Translate for technical and business contexts. Use it to draft your initial messages in Japanese, translate them, and then lightly edit the result. Over time, you will find yourself needing it less and less.</p>
<p><a href="https://www.grammarly.com/"><strong>Grammarly</strong></a> checks grammar, tone, and clarity in real time. The free version is sufficient for most needs. Install the browser extension so it works directly within the Upwork messaging interface.</p>
<p><strong>ChatGPT or similar LLMs</strong> can be invaluable for polishing your writing. Paste your draft message and ask: <em>"Please make this more professional and concise while keeping the technical meaning."</em> This is not cheating  it is using available tools effectively, which is exactly what a senior engineer should do.</p>
<h3>Practical Communication Templates</h3>
<p>Having a set of pre-written templates for common scenarios eliminates the stress of composing messages from scratch. Here are templates that work well in practice:</p>
<table>
<thead>
<tr>
<th>Scenario</th>
<th>Template</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Confirming Requirements Before Starting</strong></td>
<td>"Before I begin, I'd like to confirm my understanding of the requirements: [Your summary]. Is this correct? Are there any additional constraints I should know about?"</td>
</tr>
<tr>
<td><strong>Mid-Project Progress Update</strong></td>
<td>"Quick update: I've completed [Task A] and [Task B]. I'm currently working on [Task C] and expect to have a draft ready by [Date]. Let me know if you have any questions or feedback so far."</td>
</tr>
<tr>
<td><strong>Requesting Clarification</strong></td>
<td>"I have a question about [Specific Point]. Could you clarify [Specific Question]? This will help me ensure the final deliverable meets your expectations."</td>
</tr>
<tr>
<td><strong>Delivering Final Work</strong></td>
<td>"I've completed the project as discussed. Please find [Deliverable] attached/linked. I've also included [Documentation/Notes] to help with future maintenance. Please let me know if you have any questions or need any adjustments."</td>
</tr>
<tr>
<td><strong>Requesting a Review</strong></td>
<td>"I'm glad we could complete this project successfully. If you're happy with my work, I'd really appreciate a review on Upwork  it helps me grow on the platform. Thank you for the opportunity to work with you!"</td>
</tr>
<tr>
<td><strong>Handling a Scope Change Request</strong></td>
<td>"Thank you for the additional request. This falls outside the original project scope, but I'd be happy to help. I can complete this for an additional [Amount/Time]. Would you like to proceed?"</td>
</tr>
</tbody></table>
<p>The key principle in all of these templates is directness and clarity. Japanese communication culture often favors indirectness and implication, but in international business communication, directness is a virtue. State what you mean clearly, confirm understanding explicitly, and document everything in writing.</p>
<hr />
<h2>Profile Optimization: Your Digital Storefront</h2>
<p>Your Upwork profile is the most important asset you have on the platform. It is the first thing clients see when they receive your proposal, and it is what determines whether they click through to learn more or move on to the next candidate. A poorly optimized profile will undermine even the best proposals.</p>
<h3>Choosing Your Niche: The Counterintuitive Power of Specialization</h3>
<p>Being a "generalist" is a fatal mistake on Upwork, especially for new entrants. If your profile title is simply "Software Engineer" or "Full-Stack Developer," you will be competing against tens of thousands of profiles with similar titles and, crucially, far more Upwork reviews than you. You will lose on trust signals every time.</p>
<p>The solution is to niche down aggressively. Identify the intersection of three factors: what you are genuinely excellent at, what the market pays well for, and where you can differentiate yourself from competitors. For a Japanese engineer with 20+ years of experience, this might be:</p>
<ul>
<li><p>"Senior Java Backend Developer | Spring Boot &amp; Microservices | Financial Systems"</p>
</li>
<li><p>"AWS Cloud Architect | Migration &amp; Cost Optimization | 20+ Years Exp"</p>
</li>
<li><p>"Python Data Engineer | ETL Pipelines &amp; Apache Spark | Enterprise Scale"</p>
</li>
<li><p>"Embedded Systems Engineer | C/C++ &amp; RTOS | IoT &amp; Industrial Automation"</p>
</li>
</ul>
<p>Notice that each of these titles is specific about the technology, the type of work, and the level of experience. A client searching for "AWS migration specialist" will find the second profile immediately relevant, whereas a generic "Cloud Engineer" profile would be buried.</p>
<h3>Writing a Compelling Profile Title</h3>
<p>Your title has two jobs: to rank in Upwork's internal search algorithm and to immediately communicate your value to a human reader. The format that works best is:</p>
<p><strong>[Role] | [Primary Technology/Specialization] | [Differentiator]</strong></p>
<p>For example: <strong>"Senior Backend Engineer | Node.js &amp; PostgreSQL | API Performance Optimization"</strong></p>
<p>The vertical bars act as visual separators that make the title easy to scan. The differentiator at the end  whether it is your years of experience, a specific industry, or a particular outcome you deliver  is what makes you memorable.</p>
<h3>Crafting Your Profile Overview</h3>
<p>Your overview is a 5,000-character space that functions as your cover letter, resume summary, and sales pitch all in one. Most freelancers waste this space by listing their skills or writing a generic biography. Instead, structure it to address the client's perspective from the very first word.</p>
<p><strong>Paragraph 1  The Hook (2-3 sentences):</strong> Open with a statement that immediately resonates with your target client's pain point. Do not start with "I am a developer with X years of experience." Start with the problem you solve.</p>
<blockquote>
<p><em>"Building a scalable backend that stays fast under load is harder than it looks  and a slow API can cost you users and revenue. I specialize in designing and optimizing backend systems that handle millions of requests per day without breaking a sweat."</em></p>
</blockquote>
<p><strong>Paragraph 2  Proof of Credibility (3-4 sentences):</strong> Briefly establish your credentials with specific, quantified achievements. Avoid vague statements like "I have extensive experience." Use numbers.</p>
<blockquote>
<p><em>"Over 20 years, I've built production systems for financial institutions, e-commerce platforms, and SaaS companies across Japan and Southeast Asia. Recent highlights include reducing a client's API response time from 2.3 seconds to 180ms by redesigning their caching layer, and cutting AWS infrastructure costs by 40% through right-sizing and Reserved Instance optimization."</em></p>
</blockquote>
<p><strong>Paragraph 3  Technology Stack (2-3 sentences):</strong> List your core technologies clearly, as clients often search for specific tools.</p>
<blockquote>
<p><em>"My primary stack is Python (FastAPI, Django) and Java (Spring Boot) on the backend, with PostgreSQL and Redis for data persistence. I'm comfortable with AWS (EC2, RDS, Lambda, ECS) and have experience with GCP and Azure. I use Docker and Kubernetes for containerization and CI/CD pipelines with GitHub Actions or Jenkins."</em></p>
</blockquote>
<p><strong>Paragraph 4  Working Style and Communication (2-3 sentences):</strong> Address the trust and communication concern directly. This is especially important for Japanese engineers.</p>
<blockquote>
<p><em>"I communicate clearly in English through written messages and always confirm requirements before writing a single line of code. I provide regular progress updates and flag issues immediately rather than waiting until a deadline. My clients consistently describe me as reliable, detail-oriented, and easy to work with."</em></p>
</blockquote>
<p><strong>Paragraph 5  Call to Action (1-2 sentences):</strong> End with a clear invitation.</p>
<blockquote>
<p><em>"If you're looking for a senior engineer who delivers high-quality code on time and communicates proactively, let's talk. Feel free to send me a message with your project details."</em></p>
</blockquote>
<h3>Portfolio: Showing Real Work</h3>
<p>Even if you have no Upwork history, you can demonstrate your skills through portfolio items. Upload 3 to 5 examples of your best work. For each item, include a brief description of the problem you solved, the technologies you used, and the measurable outcome. If you cannot share client code due to NDAs, create a public GitHub repository with a well-documented personal project that demonstrates your skills at a professional level.</p>
<p>A strong portfolio item looks like this:</p>
<blockquote>
<p><strong>E-commerce Backend Optimization</strong>  Redesigned the product catalog API for a Japanese e-commerce platform serving 500,000 monthly users. Implemented Redis caching and database query optimization, reducing average response time from 1.8s to 120ms. Stack: Python, FastAPI, PostgreSQL, Redis, AWS EC2.</p>
</blockquote>
<hr />
<h2>Strategic Pricing: The First Job is a Marketing Investment</h2>
<p>One of the most common failure patterns for senior engineers entering Upwork is overpricing their initial services. The reasoning is understandable: "I have 20 years of experience, I know my market value, and I refuse to undersell myself." But this logic misses a critical point about how Upwork's marketplace actually works.</p>
<p>On Upwork, trust signals are a separate and parallel currency to skill. A developer with 50 five-star reviews charging USD 60/hr will almost always win against an unknown developer charging USD 80/hr, even if the unknown developer is objectively more skilled. Clients are risk-averse, and reviews are the primary risk-mitigation tool they have. You need to account for this in your initial pricing strategy.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/4e392933-7e7b-4895-b33d-3e3c24157ee0.jpg" alt="" style="display:block;margin:0 auto" />

<h3>The Three-Phase Pricing Strategy</h3>
<p><strong>Phase 1: The Investment Phase (First 13 Jobs)</strong></p>
<p>Set your hourly rate at 7080% of your true market rate. If your skills are worth USD 100/hr, price yourself at USD 65  USD 80/hr. This is not permanent  it is a deliberate, time-limited investment in building your platform reputation. Your goal in this phase is not profit maximization; it is to secure 35 five-star reviews as quickly as possible.</p>
<p>To accelerate this phase, focus exclusively on <strong>fixed-price contracts</strong> with a clearly defined, limited scope. A USD 200  USD 500 fixed-price project that you can complete in 510 hours is far more valuable at this stage than a USD 2,000 hourly contract that takes months. The reason is simple: fixed-price contracts generate reviews faster, and faster reviews mean faster progression to the next phase.</p>
<p><strong>Phase 2: The Rising Talent Phase (After 35 Reviews)</strong></p>
<p>Once you have earned the "Rising Talent" badge and accumulated several positive reviews, you have established proof of quality on the platform. At this point, raise your rate to your true market value. The badge and reviews will justify the higher rate in clients' eyes, and you will find that your proposal acceptance rate actually improves despite the higher price, because you now have trust signals to back it up.</p>
<p><strong>Phase 3: The Established Phase (Top Rated and Beyond)</strong></p>
<p>With a JSS above 90% and the "Top Rated" badge, you can command premium rates. At this stage, you can be selective about the projects you take, focus on higher-value clients, and build long-term relationships that reduce your effective Upwork fee from 20% to 5%.</p>
<h3>Understanding Upwork's Service Fee Impact on Your Rate</h3>
<p>When setting your rate, always calculate your take-home amount after Upwork's service fee. The fee structure is as follows:</p>
<table>
<thead>
<tr>
<th>Billing Amount (per client)</th>
<th>Upwork Fee</th>
<th>Your Take-Home %</th>
</tr>
</thead>
<tbody><tr>
<td>First USD 500</td>
<td>20%</td>
<td>80%</td>
</tr>
<tr>
<td>USD500.01  USD10,000</td>
<td>10%</td>
<td>90%</td>
</tr>
<tr>
<td>Over USD 10,000</td>
<td>5%</td>
<td>95%</td>
</tr>
</tbody></table>
<p>This means that if you charge USD 80/hr and a client hires you for the first time, you will actually receive USD 64/hr after Upwork's 20% fee. Factor this into your pricing from the start. Many new freelancers are surprised to find their first paycheck significantly smaller than expected.</p>
<p>The practical implication is that long-term client relationships are financially superior to constantly acquiring new clients. Once you have billed a client more than USD 10,000, your effective fee drops to 5%, meaning you keep 95% of your earnings from that client. This is a strong incentive to deliver excellent work and cultivate repeat business.</p>
<hr />
<h2>Identifying Winnable Jobs: The Art of Strategic Application</h2>
<p>Not all job postings are created equal. Applying to the wrong jobs wastes Connects and time. Learning to identify "winnable" jobs is one of the most important skills you can develop as a new Upwork freelancer.</p>
<h3>The Anatomy of a Winnable Job</h3>
<p>A winnable job for a new entrant has several characteristics. First, it has a <strong>low number of proposals</strong>  ideally fewer than 20. Jobs that have already received 50+ proposals are extremely difficult to win without an established track record. Second, it was <strong>posted recently</strong>  within the last 2448 hours. Older postings have already been reviewed by the client, and your proposal is less likely to be seen. Third, it has a <strong>verified payment method</strong>, which indicates the client is serious and has been vetted by Upwork. Fourth, the client has a <strong>history of hiring</strong> on the platform, meaning they know how to work with freelancers and are likely to leave a review upon completion.</p>
<h3>Filtering Jobs Effectively</h3>
<p>Use Upwork's search filters aggressively. Filter by "Payment Verified," "Less than 5 proposals" or "Less than 10 proposals," and sort by "Newest." Set up saved searches for your specific niche so you can check for new postings daily without having to repeat the filter setup.</p>
<p>For your first few jobs, also filter by <strong>project budget</strong>. Target fixed-price projects in the USD 100  USD 500 range. These are small enough that clients are less risk-averse about hiring someone without an extensive Upwork history, but large enough to generate a meaningful review. Avoid USD 10 or USD 20 micro-tasks  they are not worth your time and rarely lead to meaningful reviews.</p>
<h3>Red Flags to Avoid</h3>
<p>Some job postings are traps that waste your time or damage your JSS. Avoid jobs where the client has a history of leaving negative reviews, where the requirements are vague or change frequently, where the budget is unrealistically low for the scope described, or where the client has never successfully completed a contract with a freelancer. Also be wary of clients who ask for extensive "test tasks" before committing to a contract  a brief skills demonstration is reasonable, but hours of unpaid work is not.</p>
<hr />
<h2>Writing Winning Proposals: Proof of Reading</h2>
<p>Once you have identified a winnable job, the proposal is your primary tool for converting that opportunity into a contract. Most freelancers write terrible proposals, which means that a well-crafted proposal will stand out dramatically even without a strong review history.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/4e243abf-15c4-4640-9d4a-6c4223f16aa2.jpg" alt="" style="display:block;margin:0 auto" />

<h3>The Cardinal Sin: Generic Templates</h3>
<p>The most common and most damaging mistake is sending a generic, copy-pasted proposal. Clients receive dozens or hundreds of proposals for popular jobs, and they develop a sharp eye for templates. A proposal that starts with "Hi, I am an experienced developer with X years of experience and I am confident I can complete your project..." is immediately recognizable as a template and will be skipped.</p>
<p>The antidote is what experienced Upwork coaches call "proof of reading"  demonstrating in the very first sentence that you have actually read and understood the specific job posting. This single technique will put your proposal in the top 10% of all submissions, regardless of your review history.</p>
<h3>The Four-Part Proposal Framework</h3>
<p><strong>Part 1  The Hook (1-2 sentences):</strong> Rephrase the client's core problem in your own words. Do not summarize their job description back to them verbatim  that is lazy and obvious. Instead, demonstrate that you understand the underlying problem they are trying to solve.</p>
<p><em>Job posting:</em> "We need a developer to fix our checkout process. It's timing out and customers are abandoning their carts."</p>
<p><em>Bad hook:</em> "I see you need help with your checkout process timing out."</p>
<p><em>Good hook:</em> "Cart abandonment due to checkout timeouts is one of the most expensive technical problems an e-commerce business can have  every failed transaction is direct lost revenue. I've solved this exact issue for two other e-commerce clients."</p>
<p><strong>Part 2  Proof of Relevant Experience (3-5 sentences):</strong> Provide 12 specific, quantified examples from your past work that are directly relevant to the client's problem. Use technology names, numbers, and outcomes. This is where your 20 years of experience becomes a powerful asset.</p>
<blockquote>
<p><em>"For a Japanese retail client with 200,000 monthly transactions, I diagnosed a similar timeout issue caused by unoptimized database queries in the payment flow. By adding targeted indexes and implementing connection pooling, I reduced checkout completion time from 8 seconds to under 1 second, eliminating timeouts entirely. I also set up monitoring with Datadog to catch similar issues proactively."</em></p>
</blockquote>
<p><strong>Part 3  Proposed Approach (3-5 sentences):</strong> Briefly outline how you would approach their specific problem. This demonstrates technical competence and gives the client confidence that you have a plan. Do not write a full technical specification  just enough to show you know what you are doing.</p>
<blockquote>
<p><em>"For your project, my first step would be to add detailed logging to the checkout flow to identify exactly where the timeout is occurring. Based on my experience, the most common culprits are slow database queries, external payment gateway timeouts, or session management issues. Once I've identified the root cause, I can implement a targeted fix and add appropriate error handling and retry logic."</em></p>
</blockquote>
<p><strong>Part 4  Closing Question (1 sentence):</strong> End with a specific, relevant technical question. This serves two purposes: it shows genuine interest and curiosity, and it opens a dialogue that can convert into a contract.</p>
<blockquote>
<p><em>"Could you share what your current average checkout completion time is, and whether the timeouts are consistent or intermittent?"</em></p>
</blockquote>
<h3>Proposal Length and Tone</h3>
<p>The ideal proposal length is 150300 words. Longer proposals are rarely read in full, and shorter ones often lack sufficient proof of competence. Write in a direct, confident tone  not arrogant, but assured. Avoid excessive politeness or hedging language like "I think I might be able to help" or "I hope you will consider me." These phrases undermine your credibility.</p>
<p>Avoid using the word "I" as the first word of your proposal. Clients are focused on their problem, not on you. Start with the problem, the outcome, or a question.</p>
<hr />
<h2>Protecting Your Job Success Score (JSS): The Foundation of Long-Term Success</h2>
<p>Once you land a job, your absolute priority shifts from winning the contract to protecting your Job Success Score. The JSS is the single most important metric on your Upwork profile, and a damaged JSS is extremely difficult to recover from.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/b10d02d6-7f65-4872-9897-af718c8f080e.jpg" alt="" style="display:block;margin:0 auto" />

<h3>How JSS is Calculated</h3>
<p>Upwork does not publish the exact formula for JSS, but based on <a href="https://support.upwork.com/hc/en-us/articles/211068468">Upwork's official documentation</a> and community research, the key factors are:</p>
<ul>
<li><p><strong>Public reviews and star ratings</strong> from clients (the most heavily weighted factor)</p>
</li>
<li><p><strong>Private feedback</strong> that clients provide to Upwork separately from the public review (clients are asked to rate freelancers privately, and this score can differ from the public rating)</p>
</li>
<li><p><strong>Contract outcomes</strong>  completed contracts are positive; cancelled contracts are negative</p>
</li>
<li><p><strong>Long-term client relationships</strong>  repeat business from the same client is a strong positive signal</p>
</li>
<li><p><strong>Absence of disputes</strong>  disputes and refund requests are heavily negative</p>
</li>
</ul>
<p>The JSS is calculated on a rolling 24-month basis, meaning that older contracts have less impact over time. This is both a warning (a bad early period can haunt you for two years) and a comfort (mistakes can be recovered from with sustained good performance).</p>
<h3>The Iron Rules of JSS Protection</h3>
<p><strong>Rule 1: Never accept a job you are not 100% confident you can complete to the client's satisfaction.</strong> This sounds obvious, but the temptation to accept ambiguous or challenging jobs when you are desperate for your first review is real. Resist it. A cancelled contract or a 3-star review is far more damaging than no contract at all. If the requirements are unclear, do not accept the contract until they are fully clarified in writing.</p>
<p><strong>Rule 2: Confirm requirements before writing a single line of code.</strong> Before starting work, send the client a written summary of your understanding of the requirements and ask them to confirm. This protects you from scope creep and from the situation where you deliver exactly what was asked for but not what the client actually wanted.</p>
<p><strong>Rule 3: Communicate proactively, especially when things go wrong.</strong> If you encounter a technical obstacle, discover that the scope is larger than anticipated, or realize you will miss a deadline, communicate immediately. Do not wait until the deadline has passed. Clients can handle problems; what they cannot handle is silence and surprises. A message saying "I've hit an unexpected issue with [X]  here's what I'm doing to resolve it and my revised timeline" is almost always received positively.</p>
<p><strong>Rule 4: Deliver more than expected, at least in the early stages.</strong> In your first few jobs, go slightly beyond the stated requirements. Add a brief README, write a few unit tests, or include a short video walkthrough of your deliverable. This costs you an extra hour but dramatically increases the likelihood of a 5-star review and a repeat engagement.</p>
<p><strong>Rule 5: Request a review explicitly but gracefully.</strong> Many clients intend to leave a review but forget. When you submit your final deliverable, include a brief, genuine request: <em>"If you're happy with the work, I'd really appreciate a review on Upwork  as a new freelancer, it makes a huge difference for me."</em> Most clients respond positively to this kind of honest, human request.</p>
<hr />
<h2>Practical Knowledge on Withdrawals and Taxes</h2>
<p>For Japanese freelancers, managing withdrawals and taxes efficiently is crucial to keeping more of what you earn. The default options are rarely the best, and the tax implications are non-trivial.</p>
<h3>Withdrawal Methods: Why Wise is the Clear Winner</h3>
<p>Upwork offers several withdrawal methods, but for Japanese freelancers, the choice is clear: use <a href="https://wise.com/">Wise</a> (formerly TransferWise).</p>
<p><strong>How it works with Wise:</strong> You open a Wise account and receive a USD account number. You add this as your withdrawal method in Upwork. When you withdraw, the funds arrive in your Wise USD balance. You then convert to JPY at the real mid-market exchange rate, with a transparent fee that is typically 0.40.7% of the transaction amount.</p>
<p><strong>Why not direct bank transfer?</strong> When you withdraw directly to a Japanese bank account, Upwork converts your USD to JPY using their own exchange rate, which is typically 23% worse than the mid-market rate. They also charge a USD 0.99 withdrawal fee. On a USD 1,000 withdrawal, you might lose USD 20  USD 30 to exchange rate margin alone. Over a year of active freelancing, this adds up to hundreds of dollars.</p>
<p>The comparison is stark:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Exchange Rate</th>
<th>Fixed Fee</th>
<th>Effective Cost on USD 1,000</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Wise</strong></td>
<td>Mid-market rate</td>
<td>~ USD 57</td>
<td>~ USD 57</td>
</tr>
<tr>
<td><strong>Direct Bank Transfer</strong></td>
<td>Upwork rate (2-3% worse)</td>
<td>USD 0.99</td>
<td>~ USD 2131</td>
</tr>
</tbody></table>
<p>Setting up a Wise account is straightforward and fully online. You will need to verify your identity with a passport or driver's license. The process typically takes 13 business days.</p>
<h3>Tax Obligations for Japanese Residents</h3>
<p>This section is not legal or tax advice  consult a qualified tax professional for your specific situation. However, here are the key points that every Japanese freelancer on Upwork needs to be aware of.</p>
<p><strong>The W-8BEN Form:</strong> Upwork is a US-based company and is required by US tax law to withhold up to 30% of payments to non-US persons unless a tax treaty exemption applies. Japan has a tax treaty with the United States that reduces this withholding rate to 0% for most types of freelance income. To claim this exemption, you must complete the W-8BEN form in your Upwork tax settings. This is mandatory  if you skip it, Upwork will withhold 30% of your earnings.</p>
<p><strong>Declaring Income in Japan:</strong> Income earned through Upwork must be declared in Japan. If you are a sole proprietor (kojin jigyo nushi), this income is classified as business income (jigyo shotoku). If you are a company employee doing freelance work on the side, it is typically classified as miscellaneous income (zatsu shotoku). You must file a Kakutei Shinkoku by March 15 of the following year.</p>
<p><strong>Currency Conversion for Tax Purposes:</strong> When declaring income, you must convert USD to JPY. The standard method is to use the TTM (Telegraphic Transfer Middle) rate published by your bank on the date the income was recognized. The income recognition date is typically when the funds became available in your Upwork account, not when you withdrew them.</p>
<p><strong>Keeping Records:</strong> Download and save your Upwork transaction history and earnings certificates regularly. You will need these for your tax return. Upwork provides these documents in the Reports section of your account.</p>
<p><strong>Consumption Tax (Shouhizei):</strong> If your annual income exceeds 10 million yen, you may be required to register as a consumption tax payer and charge consumption tax on your services. For most freelancers starting out, this threshold is not immediately relevant, but it is worth being aware of.</p>
<hr />
<h2>The 4-Week Action Plan: From Zero to First Contract</h2>
<p>Breaking into the global market takes patience and systematic effort. It is entirely normal to send 20 proposals before receiving a single reply. Do not interpret silence as rejection  it is simply the reality of a competitive marketplace where clients receive dozens of proposals. Treat every non-response as data, and use it to refine your approach.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/e9c9f9e7-55e7-47c2-9edd-b4623e1d7ae0.jpg" alt="" style="display:block;margin:0 auto" />

<h3>Week 1: Foundation and Profile Setup</h3>
<p>The goal of Week 1 is to build a complete, professional presence on the platform before sending a single proposal.</p>
<p><strong>Day 12: Account Creation and Verification.</strong> Create your Upwork account and immediately complete the identity verification process. Upwork requires a government-issued ID (passport is ideal) and sometimes a video verification. This process can take 2448 hours, so start it immediately. An unverified account cannot submit proposals.</p>
<p><strong>Day 34: Profile Writing.</strong> Write your profile title, overview, and skills section following the framework described earlier in this guide. Take your time with the overview  it is worth spending 23 hours to get it right. Ask a trusted colleague or use an LLM to review it for clarity and tone.</p>
<p><strong>Day 5: Portfolio Upload.</strong> Upload at least 3 portfolio items. For each item, write a clear description of the problem, your solution, and the measurable outcome. If you have screenshots or diagrams, include them.</p>
<p><strong>Day 6: Financial Setup.</strong> Create a <a href="https://wise.com/">Wise</a> account and add your Wise USD account number as your withdrawal method in Upwork. Complete the W-8BEN form in Upwork's tax settings.</p>
<p><strong>Day 7: Market Research Preparation.</strong> Spend time browsing job postings in your niche without applying to anything. Get a feel for the types of projects being posted, the budgets clients are offering, and the language they use to describe their problems. This will inform your proposal writing.</p>
<h3>Week 2: Deep Market Research and Competitor Analysis</h3>
<p>The goal of Week 2 is to understand your competitive landscape and identify the specific types of jobs you will target.</p>
<p>Search for your niche keywords and study the profiles of the top-ranked freelancers. Note their titles, the structure of their overviews, their hourly rates, and the types of projects in their portfolios. You are not copying them  you are learning what works in your specific market.</p>
<p>Identify 1015 job postings that represent your ideal target: fixed-price, USD 100  USD 500, fewer than 20 proposals, verified payment, client with hiring history. Analyze what these clients have in common. What problems are they trying to solve? What language do they use? What red flags appear in postings you should avoid?</p>
<p>Set up saved searches in Upwork for your top 23 keyword combinations so you receive notifications when new relevant jobs are posted.</p>
<h3>Week 3: Proposal Drafting and First Applications</h3>
<p>The goal of Week 3 is to develop your proposal writing skills and start applying systematically.</p>
<p>Write a base proposal template that you will customize for each application. This template should include your hook structure, your proof of experience, and your closing question format  but it should be a framework, not a script. Every proposal you send must be genuinely customized for the specific job.</p>
<p>Apply to 12 jobs per day, focusing on quality over quantity. After each proposal, note what you wrote and how you customized it. This record will help you identify patterns in what works and what does not.</p>
<h3>Week 4: Iteration and Adjustment</h3>
<p>The goal of Week 4 is to analyze your results and optimize your approach.</p>
<p>If you have not received any responses after 20 proposals, something needs to change. Review your proposals critically: Are you starting with a genuine hook or a generic opener? Is your proof of experience specific and quantified? Is your closing question relevant and interesting? Consider asking a trusted colleague or an LLM to review your proposals for clarity and persuasiveness.</p>
<p>Also review your profile: Is your title specific enough? Does your overview address a real client pain point? Is your hourly rate competitive for your niche and experience level?</p>
<p>If you have received responses but not converted them into contracts, the issue is likely in your follow-up communication or your rate. Practice your response messages and consider whether a slight rate reduction might help you close your first contract.</p>
<hr />
<h2>Beyond the First Contract: Building Long-Term Success</h2>
<p>Landing your first contract is a milestone, but it is just the beginning. The strategies that get you your first job are different from the strategies that build a sustainable, high-income freelance career.</p>
<p>Once you have your first 5-star review, focus on converting one-time clients into long-term relationships. At the end of every successful project, ask the client if they have any upcoming work you could help with. Many clients have ongoing needs and prefer to work with a trusted freelancer they already know rather than going through the hiring process again. Long-term relationships also reduce your Upwork fee from 20% to 5% once you have billed more than USD 10,000 with that client.</p>
<p>As your JSS grows and you earn the "Top Rated" badge, gradually increase your hourly rate. Do this in increments of USD 10  USD 15 rather than large jumps, and monitor your proposal acceptance rate. The goal is to find the rate at which you are consistently winning the projects you want while earning what your skills are worth.</p>
<p>Consider developing a <strong>Project Catalog</strong>  Upwork's feature that allows you to offer pre-defined services at fixed prices, similar to Fiverr. A well-crafted catalog item can generate inbound inquiries without requiring you to spend Connects, and it positions you as a specialist with a defined, repeatable offering.</p>
<hr />
<h2>Conclusion: Your 20 Years Are Your Greatest Asset</h2>
<p>The global freelance market is not a place where experience is irrelevant  it is a place where experience, when properly communicated and strategically deployed, commands premium rates. The challenge for Japanese engineers is not a lack of skill; it is a lack of familiarity with the platform mechanics and the communication norms of international clients.</p>
<p>Your 20 years of engineering experience give you something that no amount of Upwork history can replicate: the ability to understand complex problems quickly, to anticipate issues before they arise, and to deliver production-quality work reliably. These are the qualities that turn one-time clients into long-term partners and that ultimately build a six-figure freelance income.</p>
<p>The path is clear. Build a focused, niche profile. Price your first few jobs as a marketing investment. Write proposals that prove you read the job description. Protect your JSS with meticulous communication. Use Wise for withdrawals and stay compliant with Japanese tax law. Follow the 4-week action plan, and do not give up after the first 10 rejections.</p>
<p>The global market is waiting for engineers with your skills and your commitment to quality. The first step is simply to begin.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-04-29-0155</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-04-29-0155</guid><category><![CDATA[upwork]]></category><category><![CDATA[Freelancing]]></category><category><![CDATA[Job opportunities]]></category><category><![CDATA[job search]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Rork: Building Mobile Apps with AI in Minutes]]></title><description><![CDATA[<p>The landscape of software development is undergoing a seismic shift. For years, building a native mobile application meant navigating a labyrinth of high costs, steep learning curves, and protracted development cycles. An average Minimum Viable Product (MVP) could easily cost between \(30,000 and \)150,000, taking anywhere from three to six months to reach the App Store. This barrier to entry effectively locked non-engineers and early-stage founders out of the mobile market.</p>
<p>Enter <a href="https://rork.com">Rork</a>, an AI-powered builder that promises to transform natural language prompts into fully functional, App Store-ready native mobile applications in a matter of minutes. Based on the recent presentation <a href="https://speakerdeck.com/x5gtrn/rork-building-mobile-apps-with-ai-in-minutes">"Rork: Building Mobile Apps with AI in Minutes"</a>, this article provides an engineering-focused deep dive into Rork's architecture, its practical use cases, and how it stacks up against other emerging AI builders like Lovable and Google Opal.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/rork-building-mobile-apps-with-ai-in-minutes">https://speakerdeck.com/x5gtrn/rork-building-mobile-apps-with-ai-in-minutes</a></p>

<h2>The Architecture: How Rork Generates "Real" Native Apps</h2>
<p>Unlike many no-code platforms that rely on web wrappers or Progressive Web Apps (PWAs), Rork is built on a robust, industry-standard foundation. It generates actual code that developers can inspect, modify, and deploy.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/c88a1efa-1424-4bf0-b73c-3bd54e0b283b.jpg" alt="" style="display:block;margin:0 auto" />

<h3>React Native and Expo</h3>
<p>At its core, Rork leverages <strong>React Native</strong> and the <strong>Expo SDK</strong>. This is a critical architectural choice. React Native is the framework behind massive applications like Discord, Shopify, and Coinbase, powering approximately 30% of the top 100 apps in the App Store. By utilizing Expo, Rork abstracts away the complex native build configurations (like managing Xcode workspaces or Gradle files), allowing the AI to focus purely on application logic and UI components.</p>
<p>When a user inputs a prompt, Rork's AI engine translates that natural language into structured <strong>TypeScript</strong> code. This generated code covers over 95% of standard native features, including camera access, push notifications, and local storage.</p>
<h3>The Rork Backend and External Integrations</h3>
<p>Rork doesn't just build the frontend; it provides a serverless backend infrastructure. This allows the generated applications to securely call third-party APIs without exposing sensitive keys on the client side.</p>
<p>Furthermore, Rork integrates seamlessly with the broader developer ecosystem. The platform supports direct code export to <strong>GitHub</strong>, enabling engineering teams to take the AI-generated MVP and continue development in their preferred IDE, such as Cursor or VS Code. It also features built-in integrations with OpenAI (for in-app AI features), Supabase (for database management), and tools like Figma, allowing users to recreate UIs directly from design screenshots.</p>
<h2>Practical Use Cases: From Lifestyle to Enterprise</h2>
<p>The speed at which Rork operates makes it an ideal tool for rapid prototyping and MVP development. Here are a few practical examples of what can be built:</p>
<h3>Lifestyle and Productivity</h3>
<ul>
<li><p><strong>Fitness Trackers:</strong> Apps featuring activity rings, step counters, and calorie calculators utilizing device sensors.</p>
</li>
<li><p><strong>Habit Management:</strong> Daily check-in interfaces with streak tracking and local data persistence.</p>
</li>
<li><p><strong>AI Assistants:</strong> Conversational chatbots powered by the OpenAI API, complete with voice recognition capabilities.</p>
</li>
</ul>
<h3>Business and Enterprise Tools</h3>
<ul>
<li><p><strong>Inventory Management:</strong> Internal tools utilizing the device camera for barcode scanning and real-time stock tracking.</p>
</li>
<li><p><strong>Field Service Apps:</strong> Applications for remote workers to submit reports and track locations via GPS.</p>
</li>
<li><p><strong>Investor Prototypes:</strong> Fully functional, interactive demos that founders can build in hours to secure funding, rather than waiting months for an engineering team.</p>
</li>
</ul>
<h2>The Future: Rork Max and the Apple Ecosystem</h2>
<p>While Rork currently relies on React Native for cross-platform compatibility, the roadmap points toward an even deeper native integration. Slated for release in 2026, <strong>Rork Max</strong> aims to be a dedicated Swift app builder.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/8127c72d-3ac0-473f-b140-7a8e40c93362.jpg" alt="" style="display:block;margin:0 auto" />

<p>Rork Max will expand the platform's reach beyond iOS and Android smartphones to encompass the entire Apple ecosystem, including iPad, Apple Watch, Apple TV, and Apple Vision Pro. By generating pure Swift code, Rork Max will unlock advanced native capabilities such as 3D gaming, Augmented Reality (ARKit), and deep HealthKit integration, all while allowing users to submit to the App Store without ever opening Xcode.</p>
<h2>The AI Builder Landscape: Rork vs. Lovable vs. Google Opal</h2>
<p>The AI app generation space is becoming crowded. To understand Rork's position, it is essential to compare it with other prominent tools: <a href="https://lovable.dev">Lovable</a> and <a href="https://developers.googleblog.com/introducing-opal/">Google Opal</a>. The fundamental difference lies in their target platforms and intended use cases.</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/5d574ac1-d433-4c32-9eb4-40eddbc42967.jpg" alt="" style="display:block;margin:0 auto" />

<h3>Lovable: The Web App Specialist</h3>
<p>Lovable is a full-stack AI builder dedicated to web applications. It generates code using React, TypeScript, Tailwind CSS, and integrates natively with Supabase for database management. If your goal is to build a SaaS platform, an internal web dashboard, or a Progressive Web App, Lovable is currently the superior choice. However, it does not natively compile to iOS or Android, requiring third-party wrappers if App Store deployment is necessary.</p>
<h3>Google Opal: The AI Workflow Engine</h3>
<p>Introduced by Google Labs in July 2025, Opal is an experimental, visual builder for AI workflows. It utilizes the Gemini AI model to create data-driven mini-apps. Opal is entirely free and excellent for prototyping complex AI interactions or automating tasks. However, it is not designed to generate standalone native mobile applications or full-stack web platforms.</p>
<h3>The Decision Matrix</h3>
<p>Choosing the right tool comes down to what you are trying to build:</p>
<ol>
<li><p><strong>Do you need a native mobile app for the App Store or Google Play?</strong> Choose <strong>Rork</strong>.</p>
</li>
<li><p><strong>Are you building a web-based SaaS or internal dashboard?</strong> Choose <strong>Lovable</strong>.</p>
</li>
<li><p><strong>Are you experimenting with AI workflows and data processing?</strong> Choose <strong>Google Opal</strong>.</p>
</li>
</ol>
<h2>Pricing and Accessibility</h2>
<p>Rork operates on a straightforward, credit-based pricing model designed to scale with the user's needs:</p>
<img src="https://cdn.hashnode.com/uploads/covers/62d5556b2f40e31decd90345/7231c7fd-1991-4366-aec1-27044dd77b66.jpg" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Free ($0/mo):</strong> Provides roughly 5 prompts per week. Ideal for testing and exploring the platform, but does not include EAS Build access for App Store publishing.</p>
</li>
<li><p><strong>Pro ($20/mo):</strong> Designed for solo founders and MVPs. This tier unlocks EAS Build, allowing you to compile and submit your React Native app to the App Store and Google Play.</p>
</li>
<li><p><strong>Max ($200/mo):</strong> The premium tier for the full Apple ecosystem. It generates native Swift code, compiles on a cloud Mac fleet, and supports 2-click App Store submission for iPhone, iPad, Watch, TV, and Vision Pro.</p>
</li>
</ul>
<h2>Conclusion</h2>
<p>Rork stands at the forefront of the mobile app democratization movement. By combining the power of Large Language Models with the robust architecture of React Native and Expo, it provides a viable pathway for non-engineers to bring their ideas to the App Store. For developers, it serves as a powerful accelerator, capable of generating the boilerplate and core logic of an MVP in minutes, allowing engineering teams to focus on complex, custom feature development.</p>
<p>As the AI-driven development market continues to mature, tools like Rork will transition from novelties to essential components of the modern software engineering stack.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-03-18-2155</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-03-18-2155</guid><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[AI-automation]]></category><category><![CDATA[roak]]></category><category><![CDATA[ios app development]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Python for Java Engineers: Django vs Spring Boot — A Battle-Tested Comparison for Server-Side API Development]]></title><description><![CDATA[<blockquote>
<p>"Engineers with Java design skills become the ultimate full-stack developers when they master Python."</p>
</blockquote>
<p>As a Java/Spring Boot veteran, you already understand layered architecture, dependency injection, ORM patterns, and REST API design. The good news: those mental models transfer directly. The challenge is unlearning some habits  verbose type declarations, checked exceptions, annotation-driven configuration  and replacing them with Python's more concise, "batteries included" philosophy.</p>
<p>This article walks you through every major dimension of server-side API development, comparing Spring Boot and Django side by side. By the end, you'll know exactly what to reach for and what to watch out for.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/python-for-java-engineers">https://speakerdeck.com/x5gtrn/python-for-java-engineers</a></p>

<hr />
<h2>1. Language Philosophy  "Explicit" vs "Concise"</h2>
<p>Before diving into frameworks, you need to understand the different <em>value systems</em> baked into Java and Python.</p>
<p><strong>Java's core promise</strong> is <a href="https://en.wikipedia.org/wiki/Write_once,_run_anywhere">"Write Once, Run Anywhere"</a>  a language optimized for safety, predictability, and enterprise-scale maintainability. Java rewards verbosity because verbosity is documentation. When you declare <code>private final String name;</code>, every reader of that code immediately knows mutability intent, type, and access scope. The Spring ecosystem extends this with "Convention over Configuration," giving you powerful defaults while remaining highly configurable via annotations.</p>
<p><strong>Python's core promise</strong> comes from <a href="https://peps.python.org/pep-0020/">The Zen of Python</a>: <em>"There should be one obvious way to do it."</em> Python optimizes for developer expressiveness and iteration speed. The "Batteries Included" philosophy means Python ships with a rich standard library  HTTP clients, JSON parsing, CSV handling, async primitives  all without reaching for third-party dependencies.</p>
<table>
<thead>
<tr>
<th>Java</th>
<th>Python</th>
</tr>
</thead>
<tbody><tr>
<td>Static Typing / Compiled</td>
<td>Dynamic Typing / Interpreted</td>
</tr>
<tr>
<td>Verbose but Explicit</td>
<td>Readability &amp; Conciseness First</td>
</tr>
<tr>
<td>Safety &amp; Performance First</td>
<td>Agility &amp; Expressiveness First</td>
</tr>
<tr>
<td>Enterprise Design (JVM)</td>
<td>"Batteries Included" Philosophy</td>
</tr>
<tr>
<td>"Convention over Configuration" (Spring)</td>
<td>"One Obvious Way" (Zen of Python)</td>
</tr>
</tbody></table>
<p><strong>The mental model shift:</strong> Stop thinking about Python as "Java with less syntax." Think of it as a different cultural philosophy about how much the language should trust you as the programmer.</p>
<hr />
<h2>2. Type System  Static vs Dynamic (With Type Hints)</h2>
<p>The biggest mental gear-shift for Java engineers is Python's dynamic typing. In Java, the compiler is your first line of defense:</p>
<pre><code class="language-java">// Java  compiler enforces correctness
String name = "Alice";  // Cannot assign an int here without compilation error
int age = 30;

// Java 10+: type inference for local variables
var message = "Hello";  // Still statically typed, just inferred
</code></pre>
<p>In Python, variables are just names bound to objects:</p>
<pre><code class="language-python"># Python  no type declaration needed
name = "Alice"
age = 30

# Nothing stops you from doing this (though you shouldn't):
name = 42  # Reassigning to int  Python won't complain
</code></pre>
<p><strong>But Python isn't completely type-unsafe.</strong> Since Python 3.5, <a href="https://peps.python.org/pep-0484/">PEP 484</a> introduced <strong>Type Hints</strong>  optional annotations that tools like <code>mypy</code> can statically check:</p>
<pre><code class="language-python"># Python with Type Hints  voluntary, not enforced at runtime
def greet(name: str, age: int) -&gt; str:
    return f"Hello, {name}! You are {age} years old."

# mypy will catch this:
greet("Alice", "thirty")  # error: Argument 2 to "greet" has incompatible type "str"; expected "int"
</code></pre>
<p><strong>Key insight:</strong> Type hints in Python are <em>documentation and tooling hints</em>, not runtime guarantees. <code>mypy</code> runs as a separate static analysis tool, typically in your CI/CD pipeline  not the compiler itself. Think of it as a powerful linter rather than Java's type system.</p>
<p><strong>Practical recommendation for Java engineers:</strong> Use type hints from day one. The productivity loss from not having them will frustrate you, and adding them retroactively is painful. Integrate <code>mypy</code> into your pre-commit hooks and CI pipeline.</p>
<hr />
<h2>3. Classes &amp; OOP  Reducing Boilerplate Dramatically</h2>
<p>Consider a simple Java POJO/Record:</p>
<pre><code class="language-java">// Java  verbose (without Lombok)
public class User {
    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }

    @Override
    public boolean equals(Object o) { /* ... */ }

    @Override
    public int hashCode() { /* ... */ }
}
</code></pre>
<p>With <a href="https://projectlombok.org/">Lombok</a> you'd use <code>@Value</code> or <code>@Data</code> to eliminate most of this. Python's <code>@dataclass</code> decorator (introduced in Python 3.7) is the built-in equivalent:</p>
<pre><code class="language-python">from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int
    # Auto-generates: __init__, __repr__, __eq__, __hash__
</code></pre>
<p>That's it. The <code>@dataclass</code> decorator introspects the type-annotated class attributes and generates <code>__init__</code>, <code>__repr__</code>, <code>__eq__</code>, and optionally <code>__hash__</code> for you. If you want immutability (the equivalent of Lombok's <code>@Value</code>), add <code>frozen=True</code>:</p>
<pre><code class="language-python">@dataclass(frozen=True)
class User:
    name: str
    age: int
</code></pre>
<p>For more advanced use cases  validators, field aliases, JSON serialization  look at <a href="https://docs.pydantic.dev/">Pydantic</a>, which has become the de facto standard for data validation in Python APIs:</p>
<pre><code class="language-python">from pydantic import BaseModel, EmailStr

class CreateUserRequest(BaseModel):
    name: str
    email: EmailStr  # Validates email format automatically
    age: int

# Pydantic validates on instantiation:
user = CreateUserRequest(name="Alice", email="not-an-email", age=30)
# ValidationError: value is not a valid email address
</code></pre>
<hr />
<h2>4. Exception Handling  Checked vs Unchecked</h2>
<p>Java famously has <em>checked exceptions</em>  exceptions that the compiler forces you to handle or declare:</p>
<pre><code class="language-java">// Java  IOException is a checked exception
try (var reader = Files.newBufferedReader(path)) {
    return reader.readLine();
} catch (IOException e) {
    // Must handle this  the compiler won't let you ignore it
    throw new UncheckedIOException(e);
}
</code></pre>
<p>Python has <strong>no checked exceptions</strong>. All exceptions are unchecked (similar to <code>RuntimeException</code> subclasses in Java). The <code>with</code> statement serves the same cleanup role as Java's <code>try-with-resources</code>:</p>
<pre><code class="language-python"># Python  all exceptions are unchecked
try:
    with open(path) as f:  # 'with' handles file closure automatically
        return f.read()
except OSError as e:
    raise  # Re-raises the same exception (like 'throw' in Java)
</code></pre>
<p>The <code>with</code> statement works via Python's <a href="https://docs.python.org/3/reference/datamodel.html#context-managers">Context Manager protocol</a>  any object implementing <code>__enter__</code> and <code>__exit__</code> can be used with it. Database connections, locks, and HTTP sessions all commonly implement this pattern.</p>
<p><strong>Watch out:</strong> The lack of checked exceptions means Python won't remind you to handle errors. This puts the discipline on you and your team. Use <code>mypy</code> and thorough testing to compensate.</p>
<hr />
<h2>5. Collections &amp; Iteration  Stream API vs List Comprehensions</h2>
<p>Java's <a href="https://docs.oracle.com/en/java/docs/api/java.base/java/util/stream/Stream.html">Stream API</a> is powerful but verbose:</p>
<pre><code class="language-java">// Java  filter and map a list of names
List&lt;String&gt; result = names.stream()
    .filter(n -&gt; n.startsWith("A"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());
</code></pre>
<p>Python's <strong>list comprehensions</strong> express the same logic in a single line:</p>
<pre><code class="language-python"># Python  concise and readable
result = [n.upper() for n in names if n.startswith("A")]
</code></pre>
<p>List comprehensions follow the pattern <code>[expression for item in iterable if condition]</code>. They're not just syntactic sugar  they're generally faster than equivalent <code>map()</code>/<code>filter()</code> calls in CPython because of reduced function call overhead.</p>
<p>For lazy evaluation (equivalent to Java streams before <code>.collect()</code>), Python has <strong>generator expressions</strong>  just replace <code>[]</code> with <code>()</code>:</p>
<pre><code class="language-python"># Generator  doesn't build the list in memory until consumed
result_gen = (n.upper() for n in names if n.startswith("A"))

# Only materializes when you iterate:
for name in result_gen:
    print(name)
</code></pre>
<p><strong>Other Pythonic collection patterns to know:</strong></p>
<pre><code class="language-python"># Dictionary comprehension (like Java's Collectors.toMap())
name_to_age = {user.name: user.age for user in users}

# Set comprehension
unique_domains = {email.split("@")[1] for email in emails}

# Unpacking (multiple return values  cleaner than Java)
first, *rest = [1, 2, 3, 4, 5]
# first = 1, rest = [2, 3, 4, 5]
</code></pre>
<hr />
<h2>6. Async &amp; Concurrency  GIL vs Virtual Threads</h2>
<p>This is where Java and Python diverge most significantly, and where Java engineers need to recalibrate expectations.</p>
<p><strong>Java (Java 21+)</strong> with <a href="https://openjdk.org/jeps/444">Virtual Threads (Project Loom)</a> achieves true OS-level parallelism:</p>
<pre><code class="language-java">// Java 21+  Virtual Threads for high-concurrency I/O
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -&gt; handleRequest());
}
</code></pre>
<p><strong>Python</strong> has the <a href="https://docs.python.org/3/glossary.html#term-global-interpreter-lock">GIL (Global Interpreter Lock)</a>  a mutex that prevents multiple native threads from executing Python bytecode simultaneously. This means:</p>
<ul>
<li><p><strong>CPU-bound tasks</strong>: Python threads don't actually run in parallel. Use <code>multiprocessing</code> instead.</p>
</li>
<li><p><strong>I/O-bound tasks</strong>: Python's <code>asyncio</code> shines  while one coroutine awaits I/O, the event loop runs others.</p>
</li>
</ul>
<pre><code class="language-python">import asyncio

async def fetch_data(url: str) -&gt; str:
    await asyncio.sleep(1)  # Non-blocking  event loop runs other coroutines
    return "data"

async def main():
    # Run multiple coroutines concurrently
    results = await asyncio.gather(
        fetch_data("url1"),
        fetch_data("url2"),
        fetch_data("url3"),
    )
</code></pre>
<p><strong>For Django API development</strong>, most bottlenecks are I/O-bound (database queries, HTTP calls), so <code>asyncio</code> handles concurrency well. Django has supported async views and ORM operations since <a href="https://docs.djangoproject.com/en/4.1/releases/4.1/">Django 4.1</a>.</p>
<p><strong>Python 3.13 note:</strong> The GIL is being made <a href="https://peps.python.org/pep-0703/">opt-in in CPython 3.13</a>, which may eventually enable true parallelism  watch this space.</p>
<hr />
<h2>7. Framework Overview  Django vs Spring Boot</h2>
<p>Here's the high-level comparison that should orient any Spring Boot developer:</p>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>Django</th>
<th>Spring Boot</th>
</tr>
</thead>
<tbody><tr>
<td>Philosophy</td>
<td>Batteries Included (Full Stack)</td>
<td>Modular (Enterprise)</td>
</tr>
<tr>
<td>Startup Time</td>
<td>Fast (Seconds)</td>
<td>Slower (JVM Warmup)</td>
</tr>
<tr>
<td>Memory</td>
<td>Low (~100MB)</td>
<td>Higher (~300MB+)</td>
</tr>
<tr>
<td>ORM</td>
<td>Django ORM (Standard)</td>
<td>JPA/Hibernate (Standard)</td>
</tr>
<tr>
<td>Auth</td>
<td>Built-in (<code>django.contrib.auth</code>)</td>
<td>Spring Security</td>
</tr>
<tr>
<td>Migrations</td>
<td>Auto-generated (<code>manage.py</code>)</td>
<td>Manual SQL (Flyway)</td>
</tr>
<tr>
<td>Admin UI</td>
<td>Auto-generated (Django Admin)</td>
<td>None (Custom impl.)</td>
</tr>
<tr>
<td>REST API</td>
<td>DRF (Django REST Framework)</td>
<td>Spring Web MVC</td>
</tr>
<tr>
<td>Async</td>
<td>ASGI/Channels</td>
<td>WebFlux (Reactor)</td>
</tr>
</tbody></table>
<p><strong>The key insight:</strong> Django is more like Ruby on Rails  opinionated, full-stack, with strong conventions. Spring Boot is more modular and enterprise-grade, giving you fine-grained control at the cost of more configuration.</p>
<p>For Java engineers, Spring Boot's modularity feels familiar. But don't underestimate Django's productivity advantages: auto-generated admin UI, automatic migrations, and DRF's serializer-as-DTO pattern can cut development time significantly for CRUD-heavy APIs.</p>
<hr />
<h2>8. Project Structure  Layered vs App-Based</h2>
<p>Spring Boot typically uses a layered architecture  code is organized by <em>role</em>:</p>
<pre><code class="language-plaintext">src/main/java/com/example/
 controller/
    UserController.java
 service/
    UserService.java
 repository/
    UserRepository.java
 model/
     User.java
</code></pre>
<p>Django uses an <strong>app-based structure</strong>  code is organized by <em>feature</em>:</p>
<pre><code class="language-plaintext">manage.py
config/
 settings.py
 urls.py
users/               Feature App
 models.py
 views.py
 serializers.py
 urls.py
</code></pre>
<p>Each Django "app" is a self-contained module for a feature domain. A typical project might have <code>users/</code>, <code>products/</code>, <code>orders/</code> apps, each with their own models, views, and URL routing. This maps conceptually to a microservice boundary within a monolith  useful for later extraction.</p>
<p><strong>Creating a new project:</strong></p>
<pre><code class="language-bash"># Install Django and DRF
pip install django djangorestframework

# Create project
django-admin startproject config .

# Create a feature app
python manage.py startapp users
</code></pre>
<p>Register the app in <code>config/settings.py</code>:</p>
<pre><code class="language-python">INSTALLED_APPS = [
    ...
    'rest_framework',
    'users',
]
</code></pre>
<hr />
<h2>9. Routing  Annotations vs URLconf</h2>
<p>Spring Boot defines routes via annotations directly on controller methods:</p>
<pre><code class="language-java">@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping("/{id}")
    public ResponseEntity&lt;UserDto&gt; getUser(@PathVariable Long id) {
        // ...
    }
}
</code></pre>
<p>Django centralizes routes in <code>urls.py</code> files:</p>
<pre><code class="language-python"># users/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("api/users/&lt;int:pk&gt;/", views.UserDetailView.as_view()),
    path("api/users/", views.UserListCreateView.as_view()),
]
</code></pre>
<pre><code class="language-python"># config/urls.py  root URL configuration
from django.urls import path, include

urlpatterns = [
    path("", include("users.urls")),
    path("", include("products.urls")),
]
</code></pre>
<p>With <a href="https://www.django-rest-framework.org/api-guide/routers/">Django REST Framework's Routers</a>, you can auto-generate standard CRUD routes  similar to Spring's <code>@RepositoryRestResource</code>:</p>
<pre><code class="language-python">from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register(r"users", views.UserViewSet)

urlpatterns = router.urls
# Automatically creates:
# GET    /users/        list
# POST   /users/        create
# GET    /users/{pk}/   retrieve
# PUT    /users/{pk}/   update
# DELETE /users/{pk}/   destroy
</code></pre>
<hr />
<h2>10. Request/Response Handling  DTO vs Serializer</h2>
<p>In Spring Boot, request and response handling typically uses DTOs with separate mapping logic (often <a href="https://mapstruct.org/">MapStruct</a>):</p>
<pre><code class="language-java">// Request DTO with Bean Validation
public record CreateUserRequest(
    @NotBlank String name,
    @Email String email
) {}

// Response DTO (separate from request)
public record UserDto(Long id, String name) {}

// Manual mapping or MapStruct handles Entity &lt;-&gt; DTO
</code></pre>
<p>DRF's <code>ModelSerializer</code> collapses all three concerns  DTO definition, validation, and mapping  into one class:</p>
<pre><code class="language-python">from rest_framework import serializers
from .models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "name", "email"]
        read_only_fields = ["id"]

    # Custom validation  equivalent to @Email, @NotBlank
    def validate_email(self, value):
        if User.objects.filter(email=value).exists():
            raise serializers.ValidationError("Email already registered.")
        return value
</code></pre>
<p>The serializer handles: JSON  Python dict (deserialization), Python dict  JSON (serialization), and validation  all in one class. For write operations vs read operations with different shapes, use separate serializers:</p>
<pre><code class="language-python">class UserCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["name", "email", "password"]
        extra_kwargs = {"password": {"write_only": True}}

class UserReadSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "name", "email", "created_at"]
</code></pre>
<hr />
<h2>11. ORM  JPA/Hibernate vs Django ORM</h2>
<p>JPA/Hibernate uses annotations to map entities:</p>
<pre><code class="language-java">@Entity
public class User {
    @Id @GeneratedValue
    private Long id;

    @OneToMany(fetch = FetchType.LAZY)
    private List&lt;Order&gt; orders;
}

// JPQL for complex queries
em.createQuery("SELECT u FROM User u WHERE u.name LIKE :name", User.class)
  .setParameter("name", "%alice%")
  .getResultList();
</code></pre>
<p><a href="https://docs.djangoproject.com/en/5.0/topics/db/queries/">Django ORM</a> uses Python class definitions and a fluent QuerySet API:</p>
<pre><code class="language-python">from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)

class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="orders")
    total = models.DecimalField(max_digits=10, decimal_places=2)
</code></pre>
<p>QuerySet API is lazy  no SQL is executed until you evaluate the queryset:</p>
<pre><code class="language-python"># This doesn't hit the database yet
users_qs = User.objects.filter(name__contains="alice")

# SQL executes here when the queryset is evaluated
users = list(users_qs)

# Chaining is safe and deferred
users = (
    User.objects
    .filter(name__contains="alice")
    .select_related("profile")           # JOIN (for ForeignKey)
    .prefetch_related("orders")          # Separate query (for ManyToMany/reverse FK)
    .order_by("-created_at")
    [:20]                                # LIMIT 20
)
</code></pre>
<p><strong>Critical pitfall  N+1 queries:</strong> Without <code>prefetch_related</code>/<code>select_related</code>, this is an N+1:</p>
<pre><code class="language-python">#  N+1  executes 1 + N queries
for user in User.objects.all():
    print(user.orders.count())  # Hits DB for each user

#  Optimized  2 queries total
users = User.objects.prefetch_related("orders").all()
for user in users:
    print(user.orders.count())  # Uses prefetched data
</code></pre>
<p>This is equivalent to JPA's N+1 problem with <code>FetchType.LAZY</code>. The solution in Django is <code>prefetch_related</code> (for reverse FK and M2M) and <code>select_related</code> (for FK, generates a JOIN).</p>
<p><strong>DB Migrations  Auto-generated vs Manual:</strong></p>
<p>Spring Boot typically uses <a href="https://flywaydb.org/">Flyway</a> or <a href="https://www.liquibase.org/">Liquibase</a> with manual SQL scripts. Django auto-generates migrations from model changes:</p>
<pre><code class="language-bash"># Modify your models.py, then:
python manage.py makemigrations   # Django detects changes, generates migration file
python manage.py migrate          # Applies pending migrations
</code></pre>
<p>The generated migration file is version-controlled and can be reviewed before applying  a significant productivity win over writing SQL migrations by hand.</p>
<hr />
<h2>12. Validation</h2>
<p>Spring Boot uses <a href="https://beanvalidation.org/">Bean Validation (JSR-380)</a> annotations on DTOs:</p>
<pre><code class="language-java">public record CreateUserRequest(
    @NotBlank(message = "Required")
    @Size(max = 50)
    String name,

    @Email
    String email
) {}
</code></pre>
<p>DRF serializers centralize validation:</p>
<pre><code class="language-python">class UserSerializer(serializers.ModelSerializer):
    name = serializers.CharField(
        max_length=50,
        error_messages={"blank": "Required", "max_length": "Too long"}
    )
    email = serializers.EmailField()

    def validate_age(self, value):
        if value &lt; 0:
            raise serializers.ValidationError("Age cannot be negative.")
        return value

    def validate(self, data):
        # Cross-field validation
        if data["role"] == "ADMIN" and not data.get("manager_id"):
            raise serializers.ValidationError("Admin users require a manager.")
        return data
</code></pre>
<p>For field-level validation, name the method <code>validate_&lt;field_name&gt;</code>. For object-level (cross-field) validation, override <code>validate()</code>. DRF serializers automatically return structured error responses:</p>
<pre><code class="language-json">{
    "name": ["This field may not be blank."],
    "email": ["Enter a valid email address."]
}
</code></pre>
<hr />
<h2>13. Authentication &amp; Authorization  Spring Security vs DRF</h2>
<p><a href="https://spring.io/projects/spring-security">Spring Security</a> provides extremely fine-grained control via <code>SecurityFilterChain</code>:</p>
<pre><code class="language-java">@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .authorizeHttpRequests(auth -&gt; auth
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated())
        .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
        .build();
}
</code></pre>
<p><a href="https://www.django-rest-framework.org/api-guide/permissions/">DRF's permission system</a> is declarative and simpler:</p>
<pre><code class="language-python"># Global default in settings.py
REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
    ],
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ],
}

# Per-view override
class AdminView(APIView):
    permission_classes = [IsAdminUser]

    def get(self, request):
        return Response({"message": "Admin only"})
</code></pre>
<p>For JWT authentication, <code>djangorestframework-simplejwt</code> is the standard library:</p>
<pre><code class="language-bash">pip install djangorestframework-simplejwt
</code></pre>
<p>For custom permission logic, subclass <code>BasePermission</code>:</p>
<pre><code class="language-python">class IsOwnerOrAdmin(BasePermission):
    def has_object_permission(self, request, view, obj):
        return request.user.is_staff or obj.owner == request.user
</code></pre>
<hr />
<h2>14. Testing  JUnit5/MockMvc vs pytest-django</h2>
<p>Spring Boot testing with <a href="https://junit.org/junit5/">JUnit5</a> and <a href="https://docs.spring.io/spring-framework/reference/testing/spring-mvc-test-framework.html">MockMvc</a>:</p>
<pre><code class="language-java">@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
    @Autowired MockMvc mockMvc;

    @Test
    void getUser() throws Exception {
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.name").value("Alice"));
    }
}
</code></pre>
<p><a href="https://pytest-django.readthedocs.io/">pytest-django</a> is significantly more concise:</p>
<pre><code class="language-python">import pytest

@pytest.mark.django_db
def test_get_user(client, django_user_model):
    user = django_user_model.objects.create_user(username="alice", password="pass")
    response = client.get(f"/api/users/{user.pk}/")
    assert response.status_code == 200
    assert response.json()["name"] == "alice"
</code></pre>
<p>pytest-django handles database setup and rollback automatically  each test gets a clean DB state by default. For authenticated requests:</p>
<pre><code class="language-python">@pytest.mark.django_db
def test_authenticated_endpoint(client, django_user_model):
    user = django_user_model.objects.create_user(username="alice", password="pass")
    client.force_login(user)  # No password needed in tests
    response = client.get("/api/profile/")
    assert response.status_code == 200
</code></pre>
<p>Use <a href="https://docs.pytest.org/en/stable/reference/fixtures.html">pytest fixtures</a> and <code>factory_boy</code> for clean test data setup:</p>
<pre><code class="language-python">import factory

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = User

    name = factory.Faker("name")
    email = factory.Faker("email")

# In tests:
def test_user_list(client):
    UserFactory.create_batch(5)
    response = client.get("/api/users/")
    assert len(response.json()) == 5
</code></pre>
<hr />
<h2>15. Deployment &amp; Operations</h2>
<p><strong>Spring Boot</strong> packages as a Fat JAR  all dependencies bundled:</p>
<pre><code class="language-dockerfile">FROM eclipse-temurin:21-jre-alpine
COPY target/myapp.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
</code></pre>
<p>Characteristics: single artifact, slow startup (JVM warmup <del>10-30s), higher memory (</del>300MB+).</p>
<p><strong>Django</strong> requires a WSGI/ASGI server  <a href="https://gunicorn.org/">Gunicorn</a> for synchronous, <a href="https://www.uvicorn.org/">Uvicorn</a> for async:</p>
<pre><code class="language-dockerfile">FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "config.wsgi", "--bind", "0.0.0.0:8000", "--workers", "4"]
</code></pre>
<p>Characteristics: fast startup (&lt;1s), lightweight (~100MB), but requires external process manager.</p>
<p><strong>Production configuration checklist for Django:</strong></p>
<pre><code class="language-python"># config/settings/production.py
DEBUG = False
ALLOWED_HOSTS = ["api.yourdomain.com"]
DATABASES = {
    "default": dj_database_url.config(default=os.environ["DATABASE_URL"])
}
STATIC_ROOT = BASE_DIR / "staticfiles"
</code></pre>
<p>For Kubernetes deployments, Django's fast startup makes it ideal for horizontal scaling and rolling deployments  no JVM warmup means new pods are ready in seconds.</p>
<hr />
<h2>16. Common Pitfalls for Java Engineers</h2>
<p>Based on real-world experience, here are the gotchas that trip up Java developers most often:</p>
<h3>Mutable Default Arguments</h3>
<pre><code class="language-python">#  WRONG  the list is created ONCE at function definition
def add_user(user, users=[]):
    users.append(user)
    return users

add_user("Alice")  # ["Alice"]
add_user("Bob")    # ["Alice", "Bob"]  surprising!

#  CORRECT  use None and initialize inside
def add_user(user, users=None):
    if users is None:
        users = []
    users.append(user)
    return users
</code></pre>
<h3><code>==</code> vs <code>is</code></h3>
<pre><code class="language-python"># In Java, == compares identity for objects (you use .equals() for value)
# In Python, == compares value, 'is' compares identity

a = "hello"
b = "hello"
a == b   # True  same value
a is b   # True  CPython interns small strings (but DON'T rely on this)

x = [1, 2, 3]
y = [1, 2, 3]
x == y   # True  same value
x is y   # False  different objects

# Common bug:
if user is None:  #  Correct for None checks
if user == None:  #  Works but wrong idiom
</code></pre>
<h3>GIL and CPU-bound parallelism</h3>
<pre><code class="language-python">#  Threads don't parallelize CPU-bound work
import threading
threads = [threading.Thread(target=cpu_heavy_task) for _ in range(4)]
# These run sequentially, not in parallel!

#  Use multiprocessing for CPU parallelism
from multiprocessing import Pool
with Pool(4) as p:
    results = p.map(cpu_heavy_task, data)

#  Use asyncio for I/O parallelism
import asyncio
results = await asyncio.gather(*[fetch(url) for url in urls])
</code></pre>
<h3>QuerySet Lazy Evaluation</h3>
<pre><code class="language-python">#  Triggers query inside the loop  N+1!
users = User.objects.all()  # No query yet
for user in users:
    orders = user.orders.all()  # Query per user!

#  Prefetch in one query
users = User.objects.prefetch_related("orders").all()
for user in users:
    orders = user.orders.all()  # Uses prefetched cache
</code></pre>
<h3>Indentation is Scope</h3>
<p>Coming from Java's braces, indentation errors are the most frustrating early bugs:</p>
<pre><code class="language-python">#  IndentationError  mixing spaces and tabs
def calculate():
    x = 10
	y = 20  # Tab instead of spaces  runtime error

#  Use a linter (flake8, black, ruff) to enforce consistency
</code></pre>
<p>Use <a href="https://docs.astral.sh/ruff/">ruff</a> or <a href="https://black.readthedocs.io/">black</a> for automatic formatting  set up pre-commit hooks from day one.</p>
<hr />
<h2>Performance Characteristics at a Glance</h2>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>Java / Spring Boot</th>
<th>Python / Django</th>
</tr>
</thead>
<tbody><tr>
<td>CPU Throughput</td>
<td>High (JIT)</td>
<td>Lower (GIL)</td>
</tr>
<tr>
<td>I/O Concurrency</td>
<td>High (Virtual Threads)</td>
<td>High (asyncio)</td>
</tr>
<tr>
<td>Startup Time</td>
<td>Slow (JVM)</td>
<td>Fast</td>
</tr>
<tr>
<td>Memory Efficiency</td>
<td>Medium-High</td>
<td>High (Lightweight)</td>
</tr>
<tr>
<td>Dev Velocity</td>
<td>Medium</td>
<td>High</td>
</tr>
<tr>
<td>AI/ML Ecosystem</td>
<td>Low</td>
<td>Very High</td>
</tr>
</tbody></table>
<p><strong>The honest verdict:</strong> For pure API serving at scale, Spring Boot edges out Django on CPU-heavy workloads. But for I/O-heavy APIs (which describes most web APIs  database queries, HTTP calls), the performance gap is negligible in practice. Django's developer productivity and Python's AI/ML ecosystem (NumPy, PyTorch, scikit-learn, LangChain) are compelling advantages for modern applications.</p>
<hr />
<h2>Migration Strategy  A Realistic Path from Java to Python</h2>
<p>You don't have to rewrite everything. Here's a pragmatic migration path:</p>
<p><strong>Step 1: New Microservices in Python</strong> Start greenfield services  especially AI/ML pipelines, data processing, or new feature domains  in Python/Django. Keep existing Java services as-is.</p>
<p><strong>Step 2: Adopt Type Hints + mypy from Day 1</strong> Don't skip type hints for productivity. The discipline pays off in refactoring and code review. Add <code>mypy</code> to your CI pipeline immediately.</p>
<p><strong>Step 3: Leverage DRF ViewSets</strong> Use <code>ModelViewSet</code> for standard CRUD operations  it's the DRF equivalent of Spring Data REST's <code>@RepositoryRestResource</code>. Use <code>ViewSet</code> + <code>Router</code> for custom actions.</p>
<p><strong>Step 4: Maintain Your Testing Culture</strong> Your Java testing instincts are valuable. pytest + pytest-django gives you the same unit/integration test capabilities. Don't let the reduced boilerplate tempt you into writing fewer tests.</p>
<hr />
<h2>Final Thoughts</h2>
<p>The mindset shift from Spring Boot to Django is real, but your Java experience is a genuine asset  not a liability. OOP, SOLID principles, layered architecture, and testing patterns all transfer directly.</p>
<p>What you're learning is a <em>different set of tradeoffs</em>:</p>
<ul>
<li><p>Dynamic typing in exchange for less ceremony</p>
</li>
<li><p>One large QuerySet API instead of JPQL + Criteria API</p>
</li>
<li><p>Auto-generated migrations instead of Flyway SQL scripts</p>
</li>
<li><p>Simpler permission classes instead of complex SecurityFilterChain configurations</p>
</li>
</ul>
<p>As Python's AI/ML ecosystem continues to dominate and async Python matures, the case for Python in the backend gets stronger every year. For Java engineers, the path to full-stack versatility runs straight through Python.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-02-24-0413</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-02-24-0413</guid><category><![CDATA[Python]]></category><category><![CDATA[Java]]></category><category><![CDATA[Django]]></category><category><![CDATA[backend]]></category><category><![CDATA[api]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Springboot]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[From Freelance to Full-Time: Navigating the Permanent Hire Journey for Senior Engineers]]></title><description><![CDATA[<h2 id="heading-the-two-decade-freelancers-dilemma-why-your-next-interview-isnt-just-another-gig">The Two-Decade Freelancers Dilemma: Why Your Next Interview Isnt Just Another Gig</h2>
<p>For twenty years, youve been the master of your own destiny. As a full-stack freelance engineer, youve parachuted into countless projects, solved complex problems, and delivered results with the swift efficiency that only a seasoned independent contractor can muster. Your interviews were typically a brisk, 60-minute affaira focused evaluation of your technical prowess, a quick negotiation of contract terms, and then youre off to the races. You are a known quantity, a reliable expert for hire.</p>
<p>But now, at 44, youre contemplating a different path: a permanent, full-time role. And youve discovered the rules of the game have changed entirely. The multi-stage, marathon interview process feels foreign, almost labyrinthine, compared to the transactional nature of contract work. Youre not just being evaluated for a specific task anymore; youre being assessed as a long-term investment, a cultural addition, and a future leader within an organization.</p>
<p>This transition is becoming increasingly common. The freelance economy is booming, with independent professionals collectively generating <a target="_blank" href="https://www.upwork.com/research/future-workforce-index-2025"><strong>$1.5 trillion in earnings in 2024</strong></a><strong>.</strong> Many seasoned freelancers eventually seek the stability, collaborative environment, and long-term impact of a permanent position. Full-time roles offer opportunities to see projects through from inception to scale, to mentor junior engineers over years instead of weeks, and to engrain yourself in a product and team that you truly believe in. Its a different kind of rewardone measured in growth and legacy rather than just invoice payments.</p>
<p><strong>Heres the challenge:</strong> You must reframe your extensive freelance experience for a full-time hiring mindset. This guide is your roadmap. Its designed to help youan experienced freelance engineernavigate this complex transition, understand the fundamental shift in how companies hire for permanent roles, and strategically position your two decades of independent work as your most powerful asset in landing that full-time position.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://speakerdeck.com/x5gtrn/from-freelance-to-full-time-navigating-the-permanent-hire-journey">https://speakerdeck.com/x5gtrn/from-freelance-to-full-time-navigating-the-permanent-hire-journey</a></div>
<p> </p>
<h2 id="heading-the-paradigm-shift-from-60-minute-transaction-to-8-hour-evaluation">The Paradigm Shift: From 60-Minute Transaction to 8-Hour Evaluation</h2>
<p>The most significant hurdle for a long-term freelancer is understanding the <strong>profound difference in what companies look for</strong> during full-time hiring. <strong>Freelance hiring is a transactional process</strong> optimized for speed and immediate skill validation. In contrast, <strong>permanent hiring is a relational process</strong> designed to mitigate risk and build a sustainable, cohesive team for the long run. This isnt just rhetorica stark contrast to the single-meeting freelance model [2], tech companies truly have a <em>multi-stage</em> interview process that can span several weeks, involving numerous stakeholders.</p>
<p><img src="https://private-us-east-1.manuscdn.com/sessionFile/h4HuWatm76d5iIpnrPyD7b/sandbox/LjRJH9lTOrGY4svbphcrfR-images_1770126588666_na1fn_L2hvbWUvdWJ1bnR1L2ZyZWVsYW5jZV92c19wZXJtYW5lbnQ.jpg?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9wcml2YXRlLXVzLWVhc3QtMS5tYW51c2Nkbi5jb20vc2Vzc2lvbkZpbGUvaDRIdVdhdG03NmQ1aUlwbnJQeUQ3Yi9zYW5kYm94L0xqUkpIOWxUT3JHWTRzdmJwaGNyZlItaW1hZ2VzXzE3NzAxMjY1ODg2NjZfbmExZm5fTDJodmJXVXZkV0oxYm5SMUwyWnlaV1ZzWVc1alpWOTJjMTl3WlhKdFlXNWxiblEuanBnIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNzk4NzYxNjAwfX19XX0_&amp;Key-Pair-Id=K2HSFNDJXOU9YS&amp;Signature=WbCQQ4l732IyNEPNwTbgaDztyg8wH4IBYCWeiOfhBGVf4SytWEGJlhQICeMY0RH5aoNqrAnjqsiAuNSlTcIyBnCZfZ8siNvjEQBv1l~fwWjjCVcrknm9AaTLym79zRW44E1vRU5UyKIhbnYNTOO3pQPFWwa5wr3y4cCHBGKj04Euf677wuEBPqDFU~udOLsy4J4v8Wba6DkFDRndaKxEuJKkGkcELSdFu8VXEipIcrVNiUmJBEMeksyTRhrooC9b70saxpq~pODaMiA2UcPu6kh1Kn5wKfe2eb5vmeFd06~~0QprzZH5Er55vO1gl4ZFp2zJBd9Xi4-GnOsX1IOlAA__" alt="Hiring Comparison: Freelance vs. Permanent" /></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Hiring Model</td><td>Primary Focus</td><td>Typical Evaluation Time</td><td>Key Criteria Evaluated</td><td>Ultimate Goal</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Freelance/Contract</strong></td><td>Immediate project needs</td><td>~60 minutes (single interview)</td><td>Technical skills, availability, rate</td><td><strong>Rapid deployment</strong>  fill a skill gap quickly for a specific task</td></tr>
<tr>
<td><strong>Permanent/Full-Time</strong></td><td>Long-term company growth</td><td>68+ hours across 46 interviews</td><td>Technical skills <strong>plus</strong> cultural fit, leadership potential, team collaboration, long-term vision</td><td><strong>Sustainable growth</strong>  invest in a high-impact, long-term team member</td></tr>
</tbody>
</table>
</div><p>As a freelancer, your value to clients is in your ability to parachute in and deliver a specific outcome with minimal hand-holding. The company cares that you can do <em>X</em> by <em>Y</em> date for <em>Z</em> cost  a clean transaction. As a permanent employee, however, your value extends far beyond the code you write on day one. It includes your ability to mentor junior engineers, contribute to the companys culture, influence technical strategy, and commit to the organizations long-term success. The hiring process is correspondingly extensive: its the companys mechanism for <strong>de-risking</strong> a significant investment in talent.</p>
<blockquote>
<p><strong>Why so many hoops?</strong> Because a bad hiring decision in a full-time role is costly. The wrong hire can drag down team productivity and morale, or even jeopardize product quality and security. Research shows a single bad hire can cost a company at least <strong>30% of that positions annual salary</strong> (and potentially far more when you factor in recruitment costs, project delays, and lost opportunity). Companies mitigate this risk by evaluating candidates from every possible angle  technical aptitude, problem-solving approach, teamwork, leadership, and cultural alignment. Its not paranoia; its prudent due diligence.</p>
</blockquote>
<p>In practical terms, this means <strong>more interviews with more people</strong>. Youll encounter not just the hiring manager, but also future teammates, cross-functional colleagues, and higher-ups. Theyre all asking the question: <em>If we bring this person on board, will it be a long-term success for both sides?</em> This relational focus fundamentally changes how you should prepare. Its time to switch from a <strong>contractor mindset</strong> (I can do the job, heres my rate) to a <strong>partner mindset</strong> (Im invested in your mission, and heres how Ill grow it over time).</p>
<h2 id="heading-the-four-round-gauntlet-a-freelancers-roadmap-to-success">The Four-Round Gauntlet: A Freelancers Roadmap to Success</h2>
<p>Your journey to a permanent offer will likely involve <strong>four distinct interview rounds</strong>, each with a specific purpose and set of expectations. Think of it as a gauntlet designed to examine you from different vantage points. Understanding what each round is looking for (and how it differs from a quick freelance interview) is key to putting your best foot forward at every step. Heres how to navigate them by anticipating whats being assessed and framing your freelance experience as a strength at each stage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770126785971/46105b4e-2ac7-49bd-a230-f23e075b9e0d.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-round-1-the-hr-amp-culture-screen-beyond-the-resume">Round 1: The HR &amp; Culture Screen  Beyond the Resume</h3>
<p><strong>The Goal:</strong> This initial 3045 minute conversation (often a phone or video call) with a recruiter or HR representative is a <strong>filter</strong>. Its not meant to grill your coding skills; its about assessing your general fit and motivations before investing time in deeper interviews. The HR rep is confirming your basic qualifications, communication skills, and above all, your motivations for seeking a full-time role. They need to answer one critical question: <strong>Why do you want to be a permanent employee now, after 20 years of freelancing?</strong> If you cant provide a compelling answer to that, the rest of the process may be moot.</p>
<p><strong>Whats Being Assessed:</strong></p>
<ul>
<li><p><strong>Motivation &amp; Mindset:</strong> Are you running <em>toward</em> this full-time opportunity, or merely running <em>away</em> from freelancing? HR wants to see genuine enthusiasm for joining a team long-term, not just someone who is tired of hunting for gigs.</p>
</li>
<li><p><strong>Communication &amp; Attitude:</strong> Do you communicate clearly and professionally? Do you seem adaptable and positive? (Theyre gauging how you might mesh with the company culture.)</p>
</li>
<li><p><strong>Basic Role Fit:</strong> Theyll verify high-level things like your work authorization, willingness to relocate (if applicable), salary expectations, etc., to ensure none of these are deal-breakers. Theyll also check that your experience roughly aligns with the job description.</p>
</li>
</ul>
<p><strong>The Freelancers Trap:</strong> Offering a lukewarm or purely self-focused reason for wanting a full-time job. A common answer might be, <em>Im looking for more stability.</em> While thats an honest sentiment (who wouldnt want a steady paycheck and benefits after years of variable income?), its a <strong>passive motivation</strong>. It frames you as someone seeking a safety net, not as someone eager to actively contribute value to the company. Remember, companies are not in the business of granting stability as a charity; they want to know what <strong>you</strong> will bring to <strong>them</strong>.</p>
<p>Another trap is coming off too transactional or contract-oriented in your tone. For instance, focusing on questions like contract length, overtime pay, side projects, etc., too early can raise concerns. The company might worry that youre still thinking like a free agent rather than a committed team member.</p>
<p><strong>Your Strategy: Craft a Proactive, Value-Focused Narrative</strong></p>
<p>You must articulate a compelling story for <em>why</em> youre making this career move, one that frames your freelance past as a strategic asset and positions you as excited to <strong>give</strong> to your next employer, not just get something from them. In other words, dont focus on what you want to <em>get</em> (stability, benefits, etc.); focus on what you want to <em>give</em> in a full-time capacity.</p>
<p><em>Example  Bad vs. Good Answer:</em></p>
<ul>
<li><p><strong>Bad (Passive) Answer:</strong> After 20 years of freelancing, Im looking for a more stable role with benefits and a consistent paycheck.  (This might be true, but it centers on your needs and implies youre seeking comfort. It doesnt tell the company <strong>why they should hire you</strong> for a long-term role, only why you want one.)</p>
</li>
<li><p><strong>Good (Active) Answer:</strong> Over my 20 years as a freelance engineer, Ive had the privilege of solving a huge variety of technical challenges for diverse clients in fintech, e-commerce, healthcareyou name it. That breadth of experience has given me a <em>big-picture perspective</em> on what works and what doesnt. Now Im eager to invest that knowledge in a single product and team. I want to move beyond short-term fixes and <strong>contribute to a long-term architectural vision</strong>. Im excited to mentor younger developers and help shape a technical roadmap over years, not just months. I was particularly drawn to <strong>[Company Name]</strong> because I love the work youre doing in <strong>[Specific Area]</strong>, and I can see myself dedicating the next chapter of my career to helping drive that forward.</p>
</li>
</ul>
<p>This kind of answer does a few important things: it reframes your freelance history as a plus (breadth of experience, adaptability), it signals a genuine desire for <em>depth</em> and <em>long-term impact</em>, and it flatters the company by showing youve done your homework on them. Youre not saying I want a job because I need stability; youre saying I choose <strong>your</strong> company because I believe I can add value and grow here.</p>
<p><strong>Additional Tips for Round 1:</strong></p>
<ul>
<li><p><strong>Emphasize Collaboration:</strong> HR might be attuned to whether a long-time independent worker can thrive in a team environment. You could mention, for example, <em>Even as a freelancer, I found the best projects were the ones where I collaborated closely with in-house teams. Im looking forward to being</em> fully* part of a team and contributing to a shared mission.*</p>
</li>
<li><p><strong>Address the Elephant (if prompted):</strong> If they explicitly ask why no full-time roles for 20 years, dont be defensive. Explain how freelancing was a deliberate choice that served you well (you honed certain skills, achieved variety, built a business), and now this is also a deliberate choice because youre ready for something different (scale, stability of one project, leadership opportunities, etc.). Keep it positive  youre <em>adding</em> a chapter, not closing one in defeat.</p>
</li>
<li><p><strong>Show Long-Term Interest:</strong> You can drop subtle hints that youre in it for the long haul. For example, ask a question at the end like, <em>How do people in this role typically grow over 35 years at the company?</em> This signals that youre already picturing a future there, which is exactly what HR wants to see.</p>
</li>
</ul>
<p>By the end of Round 1, you want the recruiter to think, This candidate has their head and heart in the right place for a full-time role. Theyd likely stick around and contribute. Clear this bar, and youll move on to the more in-depth evaluations.</p>
<h3 id="heading-round-2-the-technical-deep-dive-proving-youre-more-than-a-hired-gun">Round 2: The Technical Deep Dive  Proving Youre More Than a Hired Gun</h3>
<p><strong>The Goal:</strong> Now its time to face the hiring manager (e.g. CTO, Engineering Manager, or Lead Developer). This round often runs 6090 minutes and is akin to what might be an entire interview in a freelance hire<strong>but with the volume turned way up</strong>. The assumption here is that you obviously can code (your resume and Round 1 got that far). What theyre really probing is your <strong>engineering depth and architectural thinking</strong>. They want evidence that youre not just a coder who takes orders, but someone who can design systems, make high-level technical decisions, and keep up with modern engineering practices. They are looking for signals of <strong>technical leadership</strong>: can you not only execute, but also plan, architect, and guide others?</p>
<p><strong>Whats Being Assessed:</strong></p>
<ul>
<li><p><strong>System Design &amp; Architecture:</strong> Expect a system design exercise or discussion. They might say, "Lets design a simplified version of Twitter," or "How would you architect an e-commerce system at scale?" The aim is to see how you handle open-ended problems and if you understand the trade-offs in software design (scalability, consistency, security, etc.).</p>
</li>
<li><p><strong>Depth of Experience:</strong> Theyll dig into your past projects. But unlike a freelance interview that might just verify "did you use tech X to do Y?", here they want the <em>why</em> and <em>how</em> behind your technical choices. They may ask you to walk through a complex project architecture you built, challenges you overcame, and how you collaborated with others on it.</p>
</li>
<li><p><strong>Breadth of Modern Knowledge:</strong> Your ability to discuss current technologies, frameworks, and tools matters. They might not quiz you on syntax, but they could gauge if youre up-to-date.</p>
</li>
<li><p><strong>Problem-Solving Approach:</strong> Some roles still include a live coding component or algorithmic problem here. But for a senior engineer/lead role, it might be more discussion-based or reviewing code rather than a LeetCode-style quiz. They want to see how you think aloud, how you approach unfamiliar problems, and whether you write clean, logical code when needed.</p>
</li>
<li><p><strong>Leadership in Tech:</strong> If this role is for Lead Engineer, theyll also evaluate how youd mentor others technically. They might ask how you review code, how you handle disagreements on architecture in the team, etc.</p>
</li>
</ul>
<p><strong>The Freelancers Trap:</strong> Talking only about <strong>specific technologies and tasks</strong> as if checking off a list, rather than demonstrating conceptual understanding. Freelancers often bounce between projects with different tech stacks, which is great, but if you just rattle off "Ive done React here, Node there, Python there," it can pigeonhole you as a <em>utility player</em> who follows client specs, rather than a technologist who drives decisions. Another trap is underestimating the importance of design and architecture questionsfocusing too much on what you built instead of <em>how</em> you design systems.</p>
<p>Also, be careful of coming across as a solitary problem-solver. Saying "I just went off and solved X on my own" for every project might make them wonder if you can integrate into a team that requires consensus and collaboration on technical direction.</p>
<p><strong>Your Strategy: Demonstrate Architectural Ownership &amp; Vision</strong></p>
<ol>
<li><p><strong>Show Youre a System Designer, Not Just a Coder:</strong> Be prepared for that <strong>system design question</strong> and embrace it. This is your chance to shine by drawing on your broad experience. When asked, for example, to design a mini Twitter, dont jump straight into a single tech stack you used before. Instead, discuss <em>high-level components</em>: <em>"Wed need a service for tweets, a service for timelines, maybe use a distributed queue for fan-out to followers"</em>. Talk through trade-offs: SQL vs NoSQL for storing tweets, monolithic vs microservices architecture, REST API vs GraphQL for the client, etc. Justify your decisions based on requirements.</p>
</li>
<li><p><strong>Connect Your Stories to Business Impact:</strong> When discussing past projects, go beyond <em>what</em> you built and explain <em>why</em> you built it that way. Did your design improve the systems <strong>performance by 30%</strong> or cut cloud costs by 15%? Quantify results if possible.</p>
</li>
<li><p><strong>Show Youre Current (Subtly Address the Age Factor):</strong> The tech industry has a well-documented ageism problem. One study found that while 57% of CS grads are still programmers six years out of college, that number plummets to just 19% by their early 40s [3]. At 44, you must proactively counter the stereotypes by weaving in references to recent technologies, continuous learning, and modern practices (CI/CD, IaC, observability).</p>
</li>
<li><p><strong>Team Technical Leadership:</strong> Be ready for questions about guiding a team technically. Show you can lead without steamrolling, and that you use facilitation and design reviews to reach consensus.</p>
</li>
</ol>
<p>By the end of Round 2, you want the hiring manager to be convinced that <strong>This person can handle our toughest technical challenges, and elevate the teams engineering practices.</strong> In their eyes, you should transition from hired gun to potential tech lead.</p>
<h3 id="heading-round-3-the-team-collaboration-round-are-you-a-partner-or-a-solo-act">Round 3: The Team Collaboration Round  Are You a Partner or a Solo Act?</h3>
<p><strong>The Goal:</strong> Culture fit and collaboration are front and center here. This round typically involves meeting <strong>your potential peers</strong>. Theyre asking: <em>"Can we work with this person every day? Would we trust them and enjoy having them on the team?"</em></p>
<p><strong>Whats Being Assessed:</strong></p>
<ul>
<li><p><strong>Teamwork &amp; Communication:</strong> Do you listen, ask good questions, and communicate respectfully?</p>
</li>
<li><p><strong>Problem-Solving in a Group Setting:</strong> Pairing, co-design, and how you incorporate feedback.</p>
</li>
<li><p><strong>Mentorship &amp; Empathy:</strong> Are you a mentor or a know-it-all?</p>
</li>
<li><p><strong>Cultural Fit:</strong> Attitude, humility, curiosity.</p>
</li>
</ul>
<p><strong>The Freelancers Trap:</strong> Projecting an aura of "I know best." Over-indexing on I language, dismissing junior devs, or sounding overly transactional.</p>
<p><strong>Your Strategy: Showcase Humility, Empathy, and Team Spirit</strong></p>
<ul>
<li><p><strong>Use We Language</strong> and acknowledge collaboration even when you were the primary driver.</p>
</li>
<li><p><strong>Ask Before You Tell:</strong> What have you tried?, What are the constraints?</p>
</li>
<li><p><strong>Share a Story of Fallibility:</strong> A time you were wrong and what you learned.</p>
</li>
<li><p><strong>Mentor + Learn:</strong> Demonstrate you lift others up while staying curious.</p>
</li>
</ul>
<p>By the end of Round 3, you want your peers to think, <strong>Wed love to have this person on the team.</strong></p>
<h3 id="heading-round-4-the-leadership-amp-vision-round-proving-youre-a-long-term-investment">Round 4: The Leadership &amp; Vision Round  Proving Youre a Long-Term Investment</h3>
<p><strong>The Goal:</strong> Final round with a VP/CTO/CEO. Theyre asking: <strong>If we hire you, what will you do for us over the next 35 years? Are you worth betting on?</strong></p>
<p><strong>Whats Being Assessed:</strong></p>
<ul>
<li><p><strong>Long-Term Vision:</strong> Alignment with product and business direction.</p>
</li>
<li><p><strong>Leadership &amp; Initiative:</strong> Ownership beyond IC tasks.</p>
</li>
<li><p><strong>Commitment &amp; Values:</strong> Likely tenure, alignment, integrity.</p>
</li>
<li><p><strong>Executive Communication:</strong> Can you connect tech to business outcomes?</p>
</li>
</ul>
<p><strong>The Freelancers Trap:</strong> Thinking short-term (project-to-project). Not researching the company. Asking only tactical questions.</p>
<p><strong>Your Strategy: Think and Speak Like a Future Company Leader</strong></p>
<ul>
<li><p><strong>Do Your Homework  Then Show It:</strong> Reference product launches, strategic moves, market challenges.</p>
</li>
<li><p><strong>Articulate a 35 Year Story:</strong> Tie your growth to the companys growth.</p>
</li>
<li><p><strong>Frame Age as an Asset:</strong> Stability, perspective, mentorship, and long-term commitment.</p>
</li>
<li><p><strong>Ask Big-Picture Questions:</strong> Strategy, roadmap, engineering culture at scale.</p>
</li>
</ul>
<p>By the close of Round 4, you want leadership convinced that hiring you is <strong>an opportunity, not a risk</strong>.</p>
<h2 id="heading-conclusion-youre-not-starting-over-youre-leveling-up">Conclusion: Youre Not Starting Over  Youre Leveling Up</h2>
<p>The leap from a 20-year freelance career to a full-time role can feel like a different game. But youre not a beginneryoure a veteran adapting to a new arena. The key is to translate your freelance experience into signals that full-time hiring managers value: long-term commitment, team collaboration, leadership, and alignment with mission.</p>
<p>You are not just a coder for hire. You are a seasoned problem-solver, an adaptable technologist, and a potential mentor who has seen cycles of technology and business. With the right narrative, preparation, and mindset for each interview stage, you can turn your unique path into your strongest differentiator.</p>
<p>Embrace the process, tell your story with confidence, and prepare to make a lasting impacttogether.</p>
<hr />
<h3 id="heading-references">References</h3>
<p>[1] Upwork. (2025). <em>The Future Workforce Index: Evolving Talent Trends in 2025 and Beyond</em>. <a target="_blank" href="https://www.upwork.com/research/future-workforce-index-2025">https://www.upwork.com/research/future-workforce-index-2025</a></p>
<p>[2] Exponent. (2024). <em>Get a Job in Tech: Interview Process and Prep</em>. <a target="_blank" href="https://www.tryexponent.com/blog/tech-interview-process">https://www.tryexponent.com/blog/tech-interview-process</a></p>
<p>[3] Abduldattijo. (2025). <em>Ageism in Tech: Career Longevity Reality for 40+ Engineers</em>. Medium. <a target="_blank" href="https://medium.com/illumination/ageism-in-tech-career-longevity-reality-for-40-engineers-aa79b6fd8b08">https://medium.com/illumination/ageism-in-tech-career-longevity-reality-for-40-engineers-aa79b6fd8b08</a></p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-02-03-2255</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-02-03-2255</guid><category><![CDATA[recruitment]]></category><category><![CDATA[hiring]]></category><category><![CDATA[senior-software-engineer]]></category><category><![CDATA[freelance]]></category><category><![CDATA[freelancer]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[The Complete Guide to AWS IaC Tools: CloudFormation, Terraform, and CDK Compared]]></title><description><![CDATA[<p>Infrastructure as Code (IaC) has become a fundamental pillar of modern cloud operations. For anyone building on AWS at scale, the question isn't whether to use IaC, but rather which tool to choose. The decision you make today will shape your infrastructure management workflow for years to come, affecting everything from deployment velocity to team productivity and operational costs.</p>
<p>In this comprehensive guide, we'll dive deep into the three dominant IaC tools for AWS:<strong>CloudFormation</strong>,<strong>Terraform</strong>, and<strong>AWS CDK</strong>. We'll explore their architectures, compare their strengths and weaknesses, and provide a practical framework to help you make an informed decision based on your specific needs.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/the-complete-guide-to-aws-iac-tools">https://speakerdeck.com/x5gtrn/the-complete-guide-to-aws-iac-tools</a></p>

<h2><strong>Why Infrastructure as Code Matters</strong></h2>
<p>Before we dive into the tools themselves, let's establish why IaC is essential for any serious AWS deployment:</p>
<p><strong>Repeatability and Consistency</strong>: Manual infrastructure provisioning through the AWS console leads to configuration drift and human error. IaC ensures that your infrastructure can be deployed identically across multiple environments, from development to production.</p>
<p><strong>Version Control</strong>: By treating infrastructure as code, you gain the ability to track changes, review modifications through pull requests, and roll back problematic deployments. Your infrastructure becomes as auditable as your application code.</p>
<p><strong>Automation and Speed</strong>: IaC enables CI/CD pipelines for infrastructure, dramatically reducing the time from concept to deployment. What once took hours or days can now be accomplished in minutes.</p>
<p><strong>Documentation</strong>: Your IaC templates serve as living documentation of your infrastructure. Unlike diagrams that quickly become outdated, your code always reflects the current state of your system.</p>
<p><strong>Cost Management</strong>: With IaC, you can easily spin up and tear down entire environments, enabling practices like ephemeral testing environments that can significantly reduce cloud costs.</p>
<p>Now that we understand the "why," let's explore the "what" and "how" of each tool.</p>
<h2><strong>AWS CloudFormation: The Native Foundation</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768847400596/f55d6269-f769-4a0e-a227-bd68f05d7904.png" alt="" style="display:block;margin:0 auto" />

<p><a href="https://aws.amazon.com/cloudformation/">AWS CloudFormation</a>is Amazon's original IaC service, launched in 2011. As the native solution, it has the deepest integration with AWS services and serves as the foundation for many other tools, including CDK.</p>
<h3><strong>How CloudFormation Works</strong></h3>
<p>CloudFormation operates on a<strong>declarative model</strong>. You define your desired infrastructure state in JSON or YAML templates, and CloudFormation handles the complexity of creating, updating, and deleting resources in the correct order. The service maintains an internal state of your infrastructure through "stacks" - logical groupings of related resources.</p>
<p>Here's a simple example of a CloudFormation template that creates an S3 bucket:</p>
<pre><code class="language-yaml">AWSTemplateFormatVersion: '2010-09-09'
Description: Simple S3 bucket with versioning

Resources:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: my-application-bucket
      VersioningConfiguration:
        Status: Enabled
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      Tags:
        - Key: Environment
          Value: Production
        - Key: ManagedBy
          Value: CloudFormation

Outputs:
  BucketName:
    Description: Name of the S3 bucket
    Value: !Ref MyS3Bucket
    Export:
      Name: MyAppBucketName
</code></pre>
<h3><strong>CloudFormation's Key Strengths</strong></h3>
<p><strong>Native AWS Integration</strong>: CloudFormation often supports new AWS services and features on day one. When AWS launches a new service, CloudFormation support is typically available immediately or shortly after.</p>
<p><strong>Managed State</strong>: Unlike Terraform, CloudFormation manages infrastructure state internally. You don't need to worry about state file corruption, locking, or remote backend configuration. AWS handles all of this for you.</p>
<p><strong>Change Sets</strong>: Before applying changes, CloudFormation lets you preview exactly what will be modified, added, or deleted through change sets. This provides a safety net against unintended modifications.</p>
<p><strong>Stack Policies and Drift Detection</strong>: CloudFormation offers robust protection mechanisms. Stack policies can prevent accidental updates or deletions of critical resources, while drift detection identifies resources that have been manually modified outside of CloudFormation.</p>
<p><strong>No Additional Cost</strong>: CloudFormation itself is free. You only pay for the AWS resources you provision.</p>
<h3><strong>CloudFormation's Limitations</strong></h3>
<p><strong>Verbose Syntax</strong>: YAML and JSON templates can become extremely verbose for complex infrastructures. The lack of native looping constructs or conditionals makes templates repetitive and hard to maintain.</p>
<p><strong>Limited Modularity</strong>: While CloudFormation supports nested stacks, the implementation is cumbersome compared to Terraform modules or CDK constructs. Sharing and reusing infrastructure patterns across teams requires significant effort.</p>
<p><strong>AWS-Only</strong>: CloudFormation is exclusively for AWS resources. If you need to manage resources in other clouds or with third-party services, you'll need additional tools.</p>
<p><strong>Slow Evolution</strong>: The CloudFormation template syntax and feature set evolve slowly. The community has limited ability to extend or improve the core experience.</p>
<h3><strong>When to Choose CloudFormation</strong></h3>
<p>CloudFormation is the right choice when:</p>
<ul>
<li><p>You're building exclusively on AWS with no multi-cloud plans</p>
</li>
<li><p>You need guaranteed same-day support for new AWS services</p>
</li>
<li><p>Your infrastructure is relatively simple and doesn't require complex logic</p>
</li>
<li><p>You prefer AWS-native tooling and support channels</p>
</li>
<li><p>You want to avoid managing state files</p>
</li>
<li><p>Compliance requirements mandate using AWS-native tools</p>
</li>
</ul>
<h2><strong>Terraform: The Multi-Cloud Pioneer</strong></h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768847425372/1c4e97bb-fc23-4779-839c-f308e13af0e5.png" alt="" style="display:block;margin:0 auto" />

<p><a href="https://www.terraform.io/">Terraform</a>by HashiCorp has become the de facto standard for multi-cloud IaC. Launched in 2014, Terraform introduced its own configuration language (HCL) and a provider-based architecture that enables infrastructure management across hundreds of platforms.</p>
<h3><strong>How Terraform Works</strong></h3>
<p>Terraform uses a<strong>declarative approach</strong>with a more powerful syntax than CloudFormation. It maintains state in a file that tracks the relationship between your configuration and the real-world resources. When you run<code>terraform apply</code>, Terraform compares your desired configuration with the current state and determines the minimal set of changes needed.</p>
<p>Here's an equivalent S3 bucket in Terraform:</p>
<pre><code class="language-plaintext">terraform {
  required_version = "&gt;= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&gt; 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "app_bucket" {
  bucket = "my-application-bucket"

  tags = {
    Environment = "Production"
    ManagedBy   = "Terraform"
  }
}

resource "aws_s3_bucket_versioning" "app_bucket_versioning" {
  bucket = aws_s3_bucket.app_bucket.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_public_access_block" "app_bucket_pab" {
  bucket = aws_s3_bucket.app_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

output "bucket_name" {
  description = "Name of the S3 bucket"
  value       = aws_s3_bucket.app_bucket.id
}
</code></pre>
<h3><strong>Terraform's Key Strengths</strong></h3>
<p><strong>Multi-Cloud Support</strong>: Terraform's provider architecture supports AWS, Azure, Google Cloud, and hundreds of other services including GitHub, Datadog, PagerDuty, and even on-premises systems. This makes it ideal for heterogeneous infrastructure.</p>
<p><strong>Powerful Language</strong>: HCL includes built-in functions, loops (<code>for_each</code>,<code>count</code>), conditionals, and dynamic blocks that make templates more concise and maintainable than CloudFormation.</p>
<p><strong>Module Ecosystem</strong>: The<a href="https://registry.terraform.io/">Terraform Registry</a>hosts thousands of reusable modules contributed by the community and vendors. You can leverage battle-tested infrastructure patterns instead of building from scratch.</p>
<p><strong>Plan and Apply Workflow</strong>: The separation between<code>terraform plan</code>(preview) and<code>terraform apply</code>(execute) provides a clear workflow with excellent visibility into changes before they're applied.</p>
<p><strong>State Management Flexibility</strong>: While state files require management, this gives you flexibility for advanced use cases like importing existing infrastructure, moving resources between stacks, or performing surgical operations on specific resources.</p>
<p><strong>Active Community</strong>: Terraform has a massive, active community contributing modules, sharing knowledge, and driving the tool's evolution.</p>
<h3><strong>Terraform's Limitations</strong></h3>
<p><strong>State File Management</strong>: The state file is both powerful and problematic. It must be stored securely (typically in S3 with DynamoDB locking for teams), can drift out of sync with reality, and requires careful handling during refactoring.</p>
<p><strong>Learning Curve</strong>: HCL and Terraform's concepts (providers, provisioners, backends, workspaces) have a steeper learning curve than CloudFormation's more straightforward model.</p>
<p><strong>Delayed AWS Feature Support</strong>: New AWS services typically take days or weeks to be supported in the AWS provider. Critical features may lag behind CloudFormation.</p>
<p><strong>License Changes</strong>: In 2023, HashiCorp changed Terraform's license from open-source MPL to BSL (Business Source License), creating uncertainty for some enterprises. This led to the<a href="https://opentofu.org/">OpenTofu</a>fork, though most users aren't affected.</p>
<p><strong>Performance at Scale</strong>: Large Terraform configurations with thousands of resources can have slow plan/apply cycles, especially when state refresh queries many APIs.</p>
<h3><strong>When to Choose Terraform</strong></h3>
<p>Terraform is the right choice when:</p>
<ul>
<li><p>You need multi-cloud or hybrid cloud capabilities</p>
</li>
<li><p>You want maximum flexibility and control</p>
</li>
<li><p>Your infrastructure includes non-AWS services (GitHub, Datadog, DNS providers, etc.)</p>
</li>
<li><p>You value a large module ecosystem and community</p>
</li>
<li><p>You need to import and manage existing infrastructure</p>
</li>
<li><p>Your team is comfortable with operational complexity</p>
</li>
<li><p>You want to avoid vendor lock-in</p>
</li>
</ul>
<h2><strong>AWS CDK: The Developer's Choice</strong></h2>
<p><a href="https://aws.amazon.com/cdk/">AWS Cloud Development Kit</a>(CDK) represents a paradigm shift in IaC. Instead of learning a domain-specific language, CDK lets you define infrastructure using familiar programming languages: TypeScript, Python, Java, C#, and Go.</p>
<h3><strong>How CDK Works</strong></h3>
<p>CDK uses an<strong>imperative approach</strong>wrapped in an object-oriented framework. You write code using high-level constructs (classes representing infrastructure components), and CDK synthesizes this into CloudFormation templates. Ultimately, CloudFormation deploys and manages your infrastructure.</p>
<p>Here's an S3 bucket in CDK (TypeScript):</p>
<pre><code class="language-typescript">import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';

export class MyInfrastructureStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create S3 bucket with best practices built-in
    const appBucket = new s3.Bucket(this, 'MyApplicationBucket', {
      bucketName: 'my-application-bucket',
      versioned: true,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      encryption: s3.BucketEncryption.S3_MANAGED,
      enforceSSL: true,
      removalPolicy: cdk.RemovalPolicy.RETAIN,
    });

    // Export bucket name for other stacks
    new cdk.CfnOutput(this, 'BucketName', {
      value: appBucket.bucketName,
      description: 'Name of the S3 bucket',
      exportName: 'MyAppBucketName',
    });

    // Add tags
    cdk.Tags.of(appBucket).add('Environment', 'Production');
    cdk.Tags.of(appBucket).add('ManagedBy', 'CDK');
  }
}
</code></pre>
<h3><strong>CDK's Key Strengths</strong></h3>
<p><strong>Programming Language Power</strong>: CDK gives you the full power of TypeScript, Python, or Java. You can use loops, conditionals, classes, functions, and all the tooling these languages provide (IDEs, linters, testing frameworks).</p>
<p><strong>Type Safety</strong>: In languages like TypeScript, you get compile-time type checking. Many configuration errors are caught before deployment, not during runtime.</p>
<p><strong>High-Level Abstractions</strong>: CDK's construct library provides pre-built patterns that encapsulate AWS best practices. A single line of CDK code might generate dozens of CloudFormation resources configured correctly.</p>
<p><strong>Construct Hub</strong>: The<a href="https://constructs.dev/">Construct Hub</a>is a registry of reusable CDK constructs from AWS and the community, similar to Terraform modules but with the power of object-oriented composition.</p>
<p><strong>Familiar Development Workflow</strong>: Developers can use the same tools they use for application code: their favorite IDE, testing frameworks like Jest or pytest, and standard package managers.</p>
<p><strong>Testing Infrastructure</strong>: CDK makes it easy to write unit tests, integration tests, and snapshot tests for your infrastructure using familiar testing frameworks.</p>
<h3><strong>CDK's Limitations</strong></h3>
<p><strong>AWS-Only</strong>: Like CloudFormation, CDK is designed specifically for AWS. While<a href="https://developer.hashicorp.com/terraform/cdktf">CDKTF</a>(CDK for Terraform) exists, it was deprecated by HashiCorp in 2024, making multi-cloud CDK usage uncertain.</p>
<p><strong>Additional Abstraction Layer</strong>: CDK adds complexity by synthesizing to CloudFormation. Debugging issues sometimes requires understanding both CDK and the underlying CloudFormation.</p>
<p><strong>Breaking Changes</strong>: As a relatively young framework, CDK has experienced breaking changes between major versions, requiring migration work.</p>
<p><strong>Increased Build Time</strong>: The synthesis step (converting code to CloudFormation) adds time to your deployment pipeline, especially for large applications.</p>
<p><strong>Learning Curve for Ops Teams</strong>: Operations teams comfortable with declarative configs may find imperative code harder to audit and understand at a glance.</p>
<p><strong>Generated CloudFormation Complexity</strong>: CDK-generated CloudFormation templates can be very large and complex, making manual troubleshooting difficult.</p>
<h3><strong>When to Choose CDK</strong></h3>
<p>CDK is the right choice when:</p>
<ul>
<li><p>Your team consists primarily of developers rather than ops specialists</p>
</li>
<li><p>You're building exclusively on AWS</p>
</li>
<li><p>You want to leverage software engineering best practices for infrastructure</p>
</li>
<li><p>You need complex conditional logic or abstractions</p>
</li>
<li><p>You value IDE support, autocompletion, and type safety</p>
</li>
<li><p>You want to write tests for your infrastructure code</p>
</li>
<li><p>Your infrastructure and application code are maintained by the same team</p>
</li>
</ul>
<h2><strong>Side-by-Side Comparison</strong></h2>
<table>
<thead>
<tr>
<th><strong>Feature</strong></th>
<th><strong>CloudFormation</strong></th>
<th><strong>Terraform</strong></th>
<th><strong>AWS CDK</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Approach</strong></td>
<td>Declarative</td>
<td>Declarative</td>
<td>Imperative (generates declarative)</td>
</tr>
<tr>
<td><strong>Language</strong></td>
<td>YAML/JSON</td>
<td>HCL</td>
<td>TypeScript, Python, Java, C#, Go</td>
</tr>
<tr>
<td><strong>Cloud Support</strong></td>
<td>AWS only</td>
<td>Multi-cloud</td>
<td>AWS only</td>
</tr>
<tr>
<td><strong>State Management</strong></td>
<td>Managed by AWS</td>
<td>Self-managed (S3, Terraform Cloud)</td>
<td>Managed via CloudFormation</td>
</tr>
<tr>
<td><strong>Learning Curve</strong></td>
<td>Low-Medium</td>
<td>Medium-High</td>
<td>Medium (depends on language)</td>
</tr>
<tr>
<td><strong>New AWS Features</strong></td>
<td>Same-day support</td>
<td>Days-weeks delay</td>
<td>Same-day support</td>
</tr>
<tr>
<td><strong>Modularity</strong></td>
<td>Nested stacks</td>
<td>Modules</td>
<td>Constructs</td>
</tr>
<tr>
<td><strong>Community</strong></td>
<td>AWS-focused</td>
<td>Very large</td>
<td>Growing rapidly</td>
</tr>
<tr>
<td><strong>Testing</strong></td>
<td>Limited</td>
<td>Third-party tools</td>
<td>Native testing support</td>
</tr>
<tr>
<td><strong>Cost</strong></td>
<td>Free (AWS resources only)</td>
<td>Free (Terraform Cloud paid)</td>
<td>Free (AWS resources only)</td>
</tr>
<tr>
<td><strong>Best For</strong></td>
<td>AWS-native, simple-medium complexity</td>
<td>Multi-cloud, maximum flexibility</td>
<td>AWS-native, developer-centric teams</td>
</tr>
</tbody></table>
<h2><strong>Making Your Decision: A Practical Framework</strong></h2>
<p>Choosing an IaC tool isn't just about featuresit's about aligning technology with your organization's needs. Here's a structured approach:</p>
<h3><strong>1. Evaluate Your Cloud Strategy</strong></h3>
<p><strong>Question</strong>: Are you committed to AWS, or do you need multi-cloud flexibility?</p>
<ul>
<li><p><strong>Single cloud (AWS)</strong>: CloudFormation or CDK are excellent choices</p>
</li>
<li><p><strong>Multi-cloud or hybrid</strong>: Terraform is the clear winner</p>
</li>
<li><p><strong>Uncertain</strong>: Terraform provides flexibility for future changes</p>
</li>
</ul>
<h3><strong>2. Assess Team Skills and Preferences</strong></h3>
<p><strong>Question</strong>: What is your team's background and comfort level?</p>
<ul>
<li><p><strong>Operations/DevOps background</strong>: CloudFormation or Terraform (declarative approaches)</p>
</li>
<li><p><strong>Developer background</strong>: CDK leverages familiar programming paradigms</p>
</li>
<li><p><strong>Mixed team</strong>: Consider what the majority of contributors will be comfortable with</p>
</li>
</ul>
<h3><strong>3. Consider Infrastructure Complexity</strong></h3>
<p><strong>Question</strong>: How complex is your infrastructure?</p>
<ul>
<li><p><strong>Simple (&lt; 50 resources)</strong>: Any tool works; choose based on team preference</p>
</li>
<li><p><strong>Medium (50-500 resources)</strong>: Modularity becomes important; Terraform modules or CDK constructs</p>
</li>
<li><p><strong>Large (&gt; 500 resources)</strong>: CDK's abstractions or Terraform modules are essential for maintainability</p>
</li>
</ul>
<h3><strong>4. Evaluate Existing Investment</strong></h3>
<p><strong>Question</strong>: What IaC tools does your organization already use?</p>
<ul>
<li><p>Leveraging existing expertise and tooling can significantly reduce ramp-up time</p>
</li>
<li><p>Cross-team consistency often outweighs minor technical advantages</p>
</li>
<li><p>Consider Conway's Law: tool choice affects team structure and vice versa</p>
</li>
</ul>
<h3><strong>5. Future-Proof Your Decision</strong></h3>
<p><strong>Question</strong>: How might your needs change in 3-5 years?</p>
<ul>
<li><p><strong>Scaling team size</strong>: CDK and Terraform's modularity scale better than CloudFormation</p>
</li>
<li><p><strong>Expanding to new clouds</strong>: Only Terraform provides smooth multi-cloud expansion</p>
</li>
<li><p><strong>Increasing automation</strong>: All three support CI/CD, but CDK's testing capabilities are superior</p>
</li>
</ul>
<h2><strong>Project Structure Best Practices</strong></h2>
<p>Regardless of which tool you choose, organizing your IaC projects properly is crucial for long-term maintainability.</p>
<h3><strong>CloudFormation Project Structure</strong></h3>
<pre><code class="language-plaintext">infrastructure/
 templates/
    vpc.yaml
    security-groups.yaml
    database.yaml
    application.yaml
    monitoring.yaml
 parameters/
    dev.json
    staging.json
    prod.json
 scripts/
    deploy.sh
    validate.sh
 README.md
</code></pre>
<h3><strong>Terraform Project Structure</strong></h3>
<pre><code class="language-plaintext">infrastructure/
 environments/
    dev/
       main.tf
       variables.tf
       outputs.tf
       terraform.tfvars
    staging/
    prod/
 modules/
    vpc/
       main.tf
       variables.tf
       outputs.tf
    database/
    application/
 global/
    iam/
    s3-backend/
 README.md
</code></pre>
<h3><strong>CDK Project Structure</strong></h3>
<pre><code class="language-plaintext">infrastructure/
 bin/
    app.ts              # CDK app entry point
 lib/
    stacks/
       vpc-stack.ts
       database-stack.ts
       application-stack.ts
       monitoring-stack.ts
    constructs/
       secure-bucket.ts
       web-server.ts
    config/
        dev.ts
        staging.ts
        prod.ts
 test/
    vpc-stack.test.ts
    application-stack.test.ts
 cdk.json
 package.json
 tsconfig.json
 README.md
</code></pre>
<h2><strong>Real-World Migration Scenarios</strong></h2>
<h3><strong>From CloudFormation to CDK</strong></h3>
<p>If you're already using CloudFormation, CDK offers a smooth migration path:</p>
<ol>
<li><p><strong>Parallel Development</strong>: Build new resources in CDK while maintaining existing CloudFormation</p>
</li>
<li><p><strong>CDK Migrate</strong>: Use the<a href="https://docs.aws.amazon.com/cdk/v2/guide/migrate.html">CDK Migrate</a>tool to convert existing CloudFormation templates to CDK</p>
</li>
<li><p><strong>Gradual Transition</strong>: Move one stack at a time, starting with new features or less critical infrastructure</p>
</li>
</ol>
<h3><strong>From Terraform to CDK</strong></h3>
<p>This migration is more challenging due to state management differences:</p>
<ol>
<li><p><strong>CloudFormation Import</strong>: Use CloudFormation's import feature to bring Terraform-managed resources into CloudFormation/CDK</p>
</li>
<li><p><strong>Terraform Destroy</strong>: Carefully destroy resources in Terraform after confirming CloudFormation management</p>
</li>
<li><p><strong>Consider Keeping Terraform</strong>: For multi-cloud resources, maintain Terraform alongside CDK</p>
</li>
</ol>
<h3><strong>From CloudFormation/CDK to Terraform</strong></h3>
<p>When expanding to multi-cloud:</p>
<ol>
<li><p><strong>Import Existing Resources</strong>: Use<code>terraform import</code>to bring AWS resources under Terraform management</p>
</li>
<li><p><strong>Parallel Operation</strong>: Run CloudFormation and Terraform side-by-side initially</p>
</li>
<li><p><strong>Gradual Cutover</strong>: Move resources systematically, ensuring no downtime</p>
</li>
</ol>
<h2><strong>Conclusion: There's No Perfect Tool</strong></h2>
<p>The "best" IaC tool doesn't exist in absolute termsit exists relative to your specific context. Each tool has been designed with different priorities:</p>
<ul>
<li><p><strong>CloudFormation</strong>prioritizes deep AWS integration and simplicity</p>
</li>
<li><p><strong>Terraform</strong>prioritizes flexibility and multi-cloud support</p>
</li>
<li><p><strong>CDK</strong>prioritizes developer experience and software engineering best practices</p>
</li>
</ul>
<p>Your choice should align with your organization's cloud strategy, team composition, and project requirements. Many large organizations use multiple tools: Terraform for multi-cloud resources and cross-platform services, CDK for AWS-native application infrastructure, and CloudFormation for simple, stable components.</p>
<p>The most important decision isn't which tool you choose, but that you choose<em>something</em>and commit to IaC principles. Even the "wrong" IaC tool is better than no IaC at all. You can always migrate laterand with modern import capabilities, migration paths are smoother than ever.</p>
<p>Start with the tool that best fits your current needs and team capabilities. As you gain experience, you'll develop intuition for when and how to introduce additional tools. The infrastructure-as-code journey is iterative, and your toolset should evolve alongside your infrastructure requirements.</p>
<h2><strong>Additional Resources</strong></h2>
<ul>
<li><p><a href="https://docs.aws.amazon.com/cloudformation/">AWS CloudFormation Documentation</a></p>
</li>
<li><p><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs">Terraform AWS Provider Documentation</a></p>
</li>
<li><p><a href="https://docs.aws.amazon.com/cdk/">AWS CDK Documentation</a></p>
</li>
<li><p><a href="https://www.terraform-best-practices.com/">Terraform Best Practices</a></p>
</li>
<li><p><a href="https://cdkpatterns.com/">CDK Patterns</a></p>
</li>
<li><p><a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/CHAP_TemplateQuickRef.html">CloudFormation Template Snippets</a></p>
</li>
</ul>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-01-20-0316</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-01-20-0316</guid><category><![CDATA[AWS]]></category><category><![CDATA[Infrastructure as code]]></category><category><![CDATA[cloudformation]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[Devops]]></category><category><![CDATA[cloud architecture]]></category><category><![CDATA[Developer Tools]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Java vs. Go vs. TypeScript: A Senior Engineer’s Guide to Backend Development in 2026]]></title><description><![CDATA[<p>As a senior engineer, your technology choices have a lasting impact on your teams productivity, your applications performance, and your companys bottom line. The backend landscape is more diverse than ever, and the debate between established giants and modern challengers is constant. This article provides a deep, engineering-focused comparison of three major players: Java, Go, and TypeScript.</p>
<p>Well move beyond superficial comparisons and dive into the architectural nuances, performance characteristics, and concurrency models that matter for building scalable, maintainable systems in 2026 and beyond.</p>
<p><a class="embed-card" href="https://speakerdeck.com/x5gtrn/java-go-and-typescript-comparison-a-language-selection-guide-for-senior-engineers">https://speakerdeck.com/x5gtrn/java-go-and-typescript-comparison-a-language-selection-guide-for-senior-engineers</a></p>

<h2>1. Java: The Enduring Powerhouse, Reimagined</h2>
<p>Java has been the bedrock of enterprise software for decades, and for good reason. Its stability, massive ecosystem, and the power of the Java Virtual Machine (JVM) are legendary. But this isnt your grandfathers Java. With rapid, six-month release cycles, Java is evolving faster than ever. The upcoming Java 25 is a testament to this, bringing features that directly address the needs of modern cloud-native development.</p>
<h3>The JVM: A Masterpiece of Engineering</h3>
<p>The JVMs Just-In-Time (JIT) compiler is a marvel of dynamic optimization. It analyzes application hotspots at runtime and compiles critical bytecode to highly optimized native machine code. This process, which includes techniques like method inlining, escape analysis, and speculative optimization, allows Java applications to achieve performance that can rival, and sometimes surpass, native code over the long run.</p>
<h3>Structured Concurrency: Taming the Chaos</h3>
<p>For years, managing concurrency in Java meant wrestling with <code>ExecutorService</code> and <code>Future</code>, a model that often led to thread leaks and complex error handling. <a href="https://openjdk.org/jeps/525">JEP 525: Structured Concurrency</a> changes the game entirely. It introduces a paradigm where concurrent tasks are treated as a single unit of work within a defined scope.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768461733552/e8d4a294-9f7c-42a5-970b-2e9165ed23d5.jpeg" alt="" style="display:block;margin:0 auto" />

<p>This model ensures that if a task is cancelled or fails, all its subtasks are automatically cleaned up. It simplifies error handling and makes concurrent code dramatically more reliable and observable.</p>
<p>Heres a practical example of how <code>StructuredTaskScope</code> simplifies fetching data from multiple sources concurrently:</p>
<pre><code class="language-java">// Pre-Java 25: Unstructured Concurrency
Response handle() throws ExecutionException, InterruptedException {
    Future&lt;String&gt; user = executor.submit(() -&gt; findUser());
    Future&lt;Integer&gt; order = executor.submit(() -&gt; fetchOrder());
    String theUser = user.get();   // Can leak a thread if fetchOrder() fails first
    int theOrder = order.get();
    return new Response(theUser, theOrder);
}

// Java 25: Structured Concurrency
Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        Future&lt;String&gt; user = scope.fork(() -&gt; findUser());
        Future&lt;Integer&gt; order = scope.fork(() -&gt; fetchOrder());

        scope.join();           // Wait for both forks
        scope.throwIfFailed();  // Propagate errors

        return new Response(user.resultNow(), order.resultNow());
    }
}
</code></pre>
<p>With <code>StructuredTaskScope</code>, the lifetime of the concurrent operations is confined to the <code>try-with-resources</code> block. If one subtask fails, the scope is shut down, and any other running subtasks are automatically cancelled. This is a huge leap forward for writing robust concurrent applications.</p>
<h2>2. Go: Simplicity and Concurrency at Scale</h2>
<p>Go, designed by Google, was built for the cloud-native era. Its philosophy is rooted in simplicity, pragmatism, and first-class support for concurrency. This has made it the language of choice for infrastructure tooling like Docker and Kubernetes, and for high-throughput microservices.</p>
<h3>Goroutines and the M:N Scheduler</h3>
<p>Gos magic lies in its concurrency model, which is built on <em>goroutines</em> and <em>channels</em>. A goroutine is a lightweight thread managed by the Go runtime, not the operating system. You can easily run millions of them on a single machine.</p>
<p>The Go runtime uses an M:N scheduler, which multiplexes M goroutines onto N OS threads. This allows the scheduler to make intelligent decisions about how to distribute work, avoiding the overhead of OS-level context switching.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768461817841/2e53035a-22e2-4e82-b820-f2dbbbc930c9.jpeg" alt="" style="display:block;margin:0 auto" />

<h3>Channels: Sharing Memory by Communicating</h3>
<p>Instead of sharing memory and using locks to coordinate access (a common source of bugs), Go encourages a different approach: Share memory by communicating. This is achieved through <em>channels</em>, which are typed conduits that allow goroutines to send and receive values.</p>
<p>Heres an example of a worker pool pattern using goroutines and channels:</p>
<pre><code class="language-go">func worker(id int, jobs &lt;-chan int, results chan&lt;- int) {
    for j := range jobs {
        fmt.Println("worker", id, "started job", j)
        time.Sleep(time.Second) // Simulate work
        fmt.Println("worker", id, "finished job", j)
        results &lt;- j * 2
    }
}

func main() {
    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

    for w := 1; w &lt;= 3; w++ {
        go worker(w, jobs, results)
    }

    for j := 1; j &lt;= numJobs; j++ {
        jobs &lt;- j
    }
    close(jobs)

    for a := 1; a &lt;= numJobs; a++ {
        &lt;-results
    }
}
</code></pre>
<p>The <code>select</code> statement provides another powerful mechanism for handling multiple channels, allowing a goroutine to wait on several communication operations simultaneously.</p>
<h2>3. TypeScript: Unifying the Stack with Types</h2>
<p>TypeScript, a superset of JavaScript, brings static typing to the worlds most popular programming language. Its primary goal is to enable developers to build large-scale applications with confidence. With the rise of Node.js, Bun, and Deno, TypeScript is no longer just for the frontend; its a formidable backend contender.</p>
<h3>The Power of a Sophisticated Type System</h3>
<p>TypeScripts type system is incredibly powerful and flexible. It goes far beyond simple type annotations, offering advanced features like conditional types, mapped types, and powerful type inference. This allows you to model complex data structures and APIs with precision, catching errors at compile time that would otherwise surface at runtime.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768461900016/b40329f7-4930-451a-9393-afcd371649dd.jpeg" alt="" style="display:block;margin:0 auto" />

<p>Heres an example of a conditional type that creates a more flexible function signature:</p>
<pre><code class="language-typescript">// A conditional type to extract property names of a certain type
type PropertyNames&lt;T, P&gt; = { [K in keyof T]: T[K] extends P ? K : never }[keyof T];

interface User {
    id: number;
    name: string;
    email: string;
    lastLogin: Date;
}

// stringProps will be "name" | "email"
type stringProps = PropertyNames&lt;User, string&gt;;

function updateStringProperty(prop: stringProps, value: string) {
    // ... implementation
}

updateStringProperty("name", "new name"); // OK
updateStringProperty("id", 123); // Compile-time error!
</code></pre>
<p>This level of type-level programming enables the creation of highly expressive and safe libraries and frameworks, which is a key reason for TypeScripts explosive growth.</p>
<h2>Head-to-Head Comparison</h2>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Java</th>
<th>Go</th>
<th>TypeScript</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Performance</strong></td>
<td>Excellent peak throughput after JIT warmup</td>
<td>Excellent raw performance, low latency</td>
<td>Good, especially for I/O-bound tasks</td>
</tr>
<tr>
<td><strong>Concurrency Model</strong></td>
<td>Structured Concurrency (Project Loom)</td>
<td>Goroutines &amp; Channels (M:N Scheduler)</td>
<td>Async/Await (Event Loop)</td>
</tr>
<tr>
<td><strong>Type System</strong></td>
<td>Strong, static, nominal</td>
<td>Strong, static, structural</td>
<td>Strong, static, structural (gradual)</td>
</tr>
<tr>
<td><strong>Ecosystem</strong></td>
<td>Massive, mature (Maven, Spring)</td>
<td>Growing rapidly, strong in cloud-native</td>
<td>Huge (npm), shared with JavaScript</td>
</tr>
<tr>
<td><strong>Learning Curve</strong></td>
<td>Moderate to high</td>
<td>Low</td>
<td>Low to moderate (if you know JS)</td>
</tr>
<tr>
<td><strong>Ideal Use Cases</strong></td>
<td>Large enterprise systems, complex domains</td>
<td>Microservices, CLI tools, network services</td>
<td>Full-stack development, APIs, prototyping</td>
</tr>
</tbody></table>
<h2>The Senior Engineers Verdict</h2>
<p>So, which language should you choose? The answer, as always, is: <strong>it depends.</strong> A senior engineers role is to select the right tool for the job.</p>
<ul>
<li><p><strong>Choose Java when:</strong> Youre building a large, complex system with a long maintenance horizon. Your team is experienced with the JVM, and you need the battle-tested reliability and vast ecosystem that Java provides. The performance of the JVM for long-running processes is a critical requirement.</p>
</li>
<li><p><strong>Choose Go when:</strong> Your primary concerns are high concurrency, low-latency performance, and operational simplicity. Youre building cloud-native microservices, infrastructure tooling, or real-time systems where fast startup times and a small memory footprint are key.</p>
</li>
<li><p><strong>Choose TypeScript when:</strong> You want to unify your frontend and backend development with a single language. Youre building a web API, a Backend-for-Frontend (BFF), or a full-stack application, and you want to leverage the massive npm ecosystem and the safety of a powerful type system.</p>
</li>
</ul>
<p>Ultimately, the best architects are polyglots. By understanding the fundamental trade-offs between these powerful languages, you can design more robust, scalable, and maintainable systems. The future of backend development isnt about one language winning; its about leveraging the unique strengths of each to build better software.</p>
<hr />
<h3>References</h3>
<ol>
<li><p><a href="https://openjdk.org/jeps/525">JEP 525: Structured Concurrency (Sixth Preview)</a></p>
</li>
<li><p><a href="https://antonz.org/go-concurrency/internals/">Gist of Go: Concurrency internals</a></p>
</li>
<li><p><a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html">TypeScript: Documentation - Advanced Types</a></p>
</li>
</ol>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-01-15-1629</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-01-15-1629</guid><category><![CDATA[Java]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Beyond the Prompt: A Deep Dive into Manus, the AI Agent That Actually Gets Work Done]]></title><description><![CDATA[<p>As engineers, we've been inundated with AI assistants that promise to revolutionize our workflow. Yet, many of us are left with glorified chatbotstools that are great for answering questions but fall short when it comes to executing complex, multi-step tasks. We still find ourselves in the driver's seat, manually guiding the process from start to finish.</p>
<p>What if an AI could move beyond the prompt-and-response cycle? What if it could take a high-level goal, create a plan, and execute it autonomously across multiple tools and platforms? This is the promise of <a target="_blank" href="https://manus.im/"><strong>Manus AI</strong></a>, an autonomous general AI agent that functions less like a copilot and more like a fully empowered teammate.</p>
<p>With its recent <a target="_blank" href="https://www.facebook.com/business/news/manus-joins-meta-accelerating-ai-innovation-for-businesses">acquisition by Meta Platforms</a> and the release of the powerful <strong>Manus 1.6 Max</strong> engine, now is the perfect time for a deep dive into what Manus is, how it works, and why it might be the most significant tool to enter an engineer's toolkit this year.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://speakerdeck.com/x5gtrn/manus-i-agent-complete-guide">https://speakerdeck.com/x5gtrn/manus-i-agent-complete-guide</a></div>
<p> </p>
<h2 id="heading-what-is-manus-a-look-under-the-hood">What is Manus? A Look Under the Hood</h2>
<p>At its core, Manus is designed to bridge the gap from <strong>"Thought" to "Action."</strong> Unlike traditional LLMs that generate text or code in response to a query, Manus is an agentic system. It operates within a sandboxed cloud environment, equipped with a suite of toolsa web browser, a shell, a file system, and the ability to write and execute codeto carry out complex instructions.</p>
<p>Think of it as a junior developer with access to a complete dev environment. You don't tell it <em>how</em> to do every little thing; you give it a goal, and it figures out the steps.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767264440786/aec92e9f-9afd-4730-8273-15ca30ccdbd0.jpeg" alt class="image--center mx-auto" /></p>
<p>Conceptually, its architecture can be broken down into three key layers:</p>
<ol>
<li><p><strong>Intent &amp; Planning Layer:</strong> This is where Manus interprets a user's high-level goal. It breaks down a complex request like "Build a web app to track my team's OKRs" into a structured plan with distinct phases.</p>
</li>
<li><p><strong>Execution Core:</strong> This is the engine that drives the action. It selects the right tool for each step in the planwhether it's using <code>curl</code> to test an endpoint, writing a Python script to process data, or using browser automation to scrape a website.</p>
</li>
<li><p><strong>Tool Integration Layer:</strong> This provides access to the digital world. Manus can install dependencies, interact with APIs, read and write files, and browse the web, just like a human developer would.</p>
</li>
</ol>
<p>This architectural approach allows Manus to handle tasks that are asynchronous and long-running, making it fundamentally different from the session-based interactions we're used to with other AI models.</p>
<h2 id="heading-core-capabilities-for-the-modern-engineer">Core Capabilities for the Modern Engineer</h2>
<p>While Manus is a general-purpose agent, several of its features are particularly powerful for software development and engineering workflows.</p>
<h3 id="heading-1-wide-research-beyond-google-search">1. Wide Research: Beyond Google Search</h3>
<p>Engineers constantly need to research new technologies, compare frameworks, or debug obscure errors. <strong>Wide Research</strong> is Manus's capability to parallelize this process. Instead of a single search, it spawns multiple sub-agents that investigate different facets of a query across various sources simultaneously. These agents then return synthesized findings.</p>
<blockquote>
<p><strong>Use Case Example:</strong> Instead of spending an afternoon Googling, you could ask Manus: <code>"Investigate the performance trade-offs between gRPC and REST for high-throughput, low-latency microservices. Provide a summary of benchmarks, best practices for implementation in Go, and real-world case studies from tech companies."</code></p>
</blockquote>
<h3 id="heading-2-full-stack-development-from-prompt-to-deployed-app">2. Full-Stack Development: From Prompt to Deployed App</h3>
<p>This is perhaps Manus's most impressive feature. It can generate, configure, and deploy full-stack web and mobile applications from a natural language description. The generated projects are not just static pages; they are production-ready scaffolds.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Stack Type</td><td>Technologies Used</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Web Static</strong></td><td>Vite + React + TypeScript + TailwindCSS</td></tr>
<tr>
<td><strong>Web DB-User</strong></td><td>Vite + React + TS + TailwindCSS + Drizzle ORM + MySQL/TiDB + Manus-OAuth</td></tr>
<tr>
<td><strong>Mobile App</strong></td><td>Expo + React Native + TS + TailwindCSS + Drizzle ORM + MySQL/TiDB + Manus-OAuth</td></tr>
</tbody>
</table>
</div><p>With the release of Manus 1.6, this now includes <strong>mobile app development</strong> using React Native, making it a versatile tool for prototyping and building internal tools.</p>
<h3 id="heading-3-design-view-interactive-image-generation">3. Design View: Interactive Image Generation</h3>
<p>For front-end engineers and those who need to create visual assets, <strong>Design View</strong> is a new interactive canvas for AI image generation. It moves beyond simple text-to-image by allowing you to make precise, localized edits, modify in-image text, and composite multiple images. It's like having a graphic designer and a Photoshop expert available via an API.</p>
<h2 id="heading-the-game-changer-manus-16-and-the-max-advantage">The Game Changer: Manus 1.6 and the "Max" Advantage</h2>
<p>The recent <a target="_blank" href="https://manus.im/blog/manus-max-release">release of Manus 1.6</a> introduced a pivotal architectural upgrade, most notably the <strong>Manus 1.6 Max</strong> agent. While the standard agent is highly capable, the Max version represents a significant leap in planning and problem-solving.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767264468819/ef6466f3-03f4-4c09-8833-5e43034a6ed2.jpeg" alt class="image--center mx-auto" /></p>
<p>So, what's the difference for an engineer?</p>
<ul>
<li><p><strong>Higher Task Success Rate:</strong> The Max engine is significantly better at completing complex, multi-step tasks in a single attempt without needing human clarification or intervention. Internal benchmarks show a <strong>19.2% increase in user satisfaction</strong>, largely due to this improved reliability.</p>
</li>
<li><p><strong>Advanced Reasoning:</strong> Max can handle more ambiguity and has a more robust planning architecture. This makes it better suited for tasks like refactoring a complex piece of code, migrating a database schema, or performing sophisticated data analysis from a raw spreadsheet.</p>
</li>
<li><p><strong>Smarter Tool Use:</strong> Max demonstrates more intelligent and efficient use of its available tools, leading to faster and more accurate results, especially in web development and spreadsheet manipulation tasks.</p>
</li>
</ul>
<p>Think of it as the difference between a junior and a mid-level developer. Both can get the job done, but the latter requires less supervision and can handle more complex challenges autonomously.</p>
<h2 id="heading-automate-your-engineering-workflow-with-scheduled-tasks">Automate Your Engineering Workflow with Scheduled Tasks</h2>
<p>One of the most practical applications for engineers is the <strong>Scheduled Tasks</strong> feature. This allows you to automate recurring, time-consuming work, turning Manus into a tireless cron job executor with advanced intelligence.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767264496451/5c3cc67a-4f68-4c12-9418-07457a1a97bc.jpeg" alt class="image--center mx-auto" /></p>
<p>Setting up a scheduled task is straightforward. You provide a clear, specific prompt and define a schedule using cron syntax or simple intervals.</p>
<h3 id="heading-10-scheduled-tasks-for-everyday-productivity">10 Scheduled Tasks for Everyday Productivity</h3>
<p>Beyond engineering workflows, Manus's Scheduled Tasks feature is equally powerful for automating personal and professional routines. Here are 10 examples that anyone can use to reclaim hours of their week:</p>
<ol>
<li><p><strong>Daily News Digest:</strong> <code>"Every morning at 7 AM, search major news outlets for topics I'm interested in (technology, business, health). Summarize the top 5 stories and email me a digest."</code></p>
</li>
<li><p><strong>Weekly Budget Analysis:</strong> <code>"Every Sunday, analyze my weekly spending data. Categorize expenses, visualize the breakdown in a chart, and provide 3 actionable tips for saving money."</code></p>
</li>
<li><p><strong>Subscription Management:</strong> <code>"On the 1st of every month, compile a list of all my active subscriptions with their costs and usage frequency. Identify any subscriptions I haven't used in 30+ days and suggest optimizations."</code></p>
</li>
<li><p><strong>Travel Plan Updates:</strong> <code>"Every day at 6 PM during my upcoming trip, check for weather forecasts, local events, and any travel advisories for my destination. Send me a daily briefing."</code></p>
</li>
<li><p><strong>Anniversary &amp; Birthday Reminders:</strong> <code>"Two weeks before any birthday or anniversary in my calendar, remind me with personalized gift ideas based on the person's interests and our relationship history."</code></p>
</li>
<li><p><strong>Language Learning Assistant:</strong> <code>"Every evening at 8 PM, send me 10 new vocabulary words in [target language] appropriate for my level, with example sentences and a mini-quiz on yesterday's words."</code></p>
</li>
<li><p><strong>Investment Portfolio Report:</strong> <code>"Every Friday at market close, summarize my stock portfolio's weekly performance. Highlight significant price movements and any relevant news about my holdings."</code></p>
</li>
<li><p><strong>Health &amp; Fitness Management:</strong> <code>"Every Sunday, analyze my weekly activity data (steps, sleep, exercise). Identify trends, compare to my goals, and suggest a personalized fitness plan for the coming week."</code></p>
</li>
<li><p><strong>Hobby &amp; Interest Curator:</strong> <code>"Twice a week, search for the latest news, new products, and upcoming events related to my hobbies (photography, gaming, cooking). Compile them into a personalized newsletter."</code></p>
</li>
<li><p><strong>Weekly Recipe Suggestions:</strong> <code>"Every Sunday morning, suggest a meal plan for the week based on seasonal ingredients and my dietary preferences. Include a consolidated grocery shopping list organized by store section."</code></p>
</li>
</ol>
<p>These tasks demonstrate how Manus can serve as a personal assistant that works around the clock, handling the repetitive information-gathering and analysis tasks that often consume our free time.</p>
<h3 id="heading-10-scheduled-tasks-to-automate-your-engineering-life">10 Scheduled Tasks to Automate Your Engineering Life</h3>
<p>Here are 10 examples of how you can leverage this feature, inspired by the official <a target="_blank" href="https://manus.im/docs/features/scheduled-tasks">Scheduled Tasks documentation</a>:</p>
<ol>
<li><p><strong>Daily Tech Trend Report:</strong> <code>"Every weekday at 8 AM EST, search Hacker News, GitHub Trending, and top tech blogs for the most significant news in AI and Go. Summarize the top 5 stories with links and post them to the #tech-trends Slack channel."</code></p>
</li>
<li><p><strong>Dependency Vulnerability Scans:</strong> <code>"Every Monday at 9 AM, scan the package.json in our main repository, check for new critical vulnerabilities in our dependencies using the npm audit API, and email a summary report to the security team."</code></p>
</li>
<li><p><strong>Pull Request Nag:</strong> <code>"Twice a day, at 10 AM and 4 PM, get the list of open pull requests in our GitHub repo that are more than 2 days old and have no recent comments. Gently remind the assigned reviewers in the #dev-team Slack channel."</code></p>
</li>
<li><p><strong>API Uptime &amp; Latency Monitoring:</strong> <code>"Every 15 minutes, hit our production /health endpoint. If the response is not 200 OK or latency exceeds 500ms, create a PagerDuty incident."</code></p>
</li>
<li><p><strong>Competitor Tech Stack Analysis:</strong> <code>"On the first of every month, analyze the public-facing websites of our top 3 competitors. Identify any changes in their tech stack (e.g., new JavaScript libraries, different hosting provider) and compile a report."</code></p>
</li>
<li><p><strong>Cloud Cost Anomaly Detection:</strong> <code>"Every morning, pull the daily AWS Cost Explorer report. Identify any service whose cost increased by more than 20% day-over-day and flag it for review."</code></p>
</li>
<li><p><strong>Official Documentation Watcher:</strong> <code>"Once a day, check the official documentation for the Stripe API for any changes or new feature announcements. Post a summary of any diffs to #api-updates."</code></p>
</li>
<li><p><strong>"Good First Issue" Finder:</strong> <code>"Every Friday, search GitHub for open issues in popular open-source Go projects tagged with 'good first issue' or 'help wanted'. Curate a list of 10 interesting issues for our team's OSS contribution day."</code></p>
</li>
<li><p><strong>Conference CFP Tracker:</strong> <code>"Every Monday, search for new Calls for Papers (CFPs) for major DevOps and SRE conferences with deadlines in the next 60 days. Add them to our shared Notion database."</code></p>
</li>
<li><p><strong>Personalized Learning Plan:</strong> <code>"Every Sunday, analyze my GitHub contributions from the past week. Based on the languages and frameworks used, find and suggest 3 high-quality articles or tutorials to help me improve in those areas."</code></p>
</li>
</ol>
<h2 id="heading-the-meta-acquisition-what-it-means-for-the-future">The Meta Acquisition: What It Means for the Future</h2>
<p>In December 2025, <a target="_blank" href="https://www.facebook.com/business/news/manus-joins-meta-accelerating-ai-innovation-for-businesses">Meta Platforms announced its acquisition of Manus</a> in a deal valued at over $2 billion. While this sent ripples through the AI community, the key takeaway for users is stability and growth. Manus continues to operate as an independent entity, but with the vast resources and infrastructure of Meta behind it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767264528245/4e81c336-2e9c-4e18-9571-5b51e9e06ca9.jpeg" alt class="image--center mx-auto" /></p>
<p>For engineers, this partnership could lead to:</p>
<ul>
<li><p><strong>Deeper Integrations:</strong> Tighter, more powerful integrations with Meta's extensive open-source ecosystem, including PyTorch and React Native.</p>
</li>
<li><p><strong>Enhanced Scalability:</strong> Access to Meta's world-class infrastructure will undoubtedly improve the performance and reliability of the Manus platform.</p>
</li>
<li><p><strong>Accelerated Innovation:</strong> A massive injection of capital and research talent will likely speed up the development of new features and capabilities.</p>
</li>
</ul>
<h2 id="heading-conclusion-from-instruction-taker-to-problem-solver">Conclusion: From Instruction-Taker to Problem-Solver</h2>
<p>Manus AI represents a significant step toward the future of AI-powered development. It shifts the paradigm from AI as a simple instruction-taker to AI as an autonomous problem-solver. By giving it high-level goals, access to tools, and the ability to plan and execute, we can offload entire categories of complex work.</p>
<p>With the power of the 1.6 Max engine and the utility of Scheduled Tasks, Manus is more than just another AI toolit's a platform for building automated systems and augmenting an engineering team's capabilities. Whether you're looking to automate tedious daily checks, accelerate prototyping, or conduct deep technical research, Manus is a tool that deserves a place in your workflow.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-01-02-0324</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-01-02-0324</guid><category><![CDATA[AI]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[automation]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[manus]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Beyond Autocomplete: A Deep Dive into Google's Agent-Driven IDE, Antigravity]]></title><description><![CDATA[<p>For decades, the core of software development has remained unchanged: a developer, a keyboard, and a wall of text. Our tools have gotten smarter, with syntax highlighting, linting, and now AI-powered autocompletion. But these are incremental improvements on the same fundamental process. We are still the ones manually translating ideas into code, line by painstaking line.</p>
<p><a target="_blank" href="https://antigravity.google/">Google Antigravity</a> proposes a radical departure from this model. Announced in November 2025 alongside Gemini 3, it's not just another IDE or a smarter autocomplete [1]. It's a foundational shift in how we build softwarean <strong>agent-driven development environment</strong> where the engineer's role evolves from a coder to an architect.</p>
<p>This article is a deep dive for engineers into what Google Antigravity is, the paradigm shift it represents, and how you can leverage it in your daily workflow. We'll go beyond the marketing and explore the practical application with examples, screenshots, and code snippets. Whether you're a frontend developer, backend engineer, or full-stack architect, understanding this new paradigm could fundamentally change how you approach software development.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://speakerdeck.com/x5gtrn/google-antigravity-the-next-gen-ide">https://speakerdeck.com/x5gtrn/google-antigravity-the-next-gen-ide</a></div>
<p> </p>
<h2 id="heading-the-new-paradigm-architect-vs-implementer">The New Paradigm: Architect vs. Implementer</h2>
<p>The central philosophy of Antigravity is the separation of roles: the <strong>human is the Architect</strong>, and the <strong>AI is the Implementer</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767259923209/37ddba30-16d9-4316-b30f-2f8ac64be89e.jpeg" alt class="image--center mx-auto" /></p>
<ul>
<li><p><strong>The Architect (You):</strong> Your role is to handle the high-level design, define the requirements, set the direction, and make critical decisions. You communicate your vision to the agent in natural language.</p>
</li>
<li><p><strong>The Implementer (The Agent):</strong> The AI agent, powered by Google's long-context Gemini 3 Pro model, takes your instructions and performs the groundwork. It writes the boilerplate, implements the logic, generates tests, fixes bugs, and even performs research.</p>
</li>
</ul>
<p>This isn't about replacing developers. It's about augmenting them, freeing them from the tedious, repetitive aspects of coding to focus on what truly matters: creative problem-solving and robust system design.</p>
<h2 id="heading-a-tour-of-the-antigravity-ide">A Tour of the Antigravity IDE</h2>
<p>Antigravity is built on an Electron-based fork of VS Code, so the interface will feel immediately familiar. However, it's augmented with several key components designed for agentic development.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767260084328/4451d03b-be03-4b9a-bb0f-32a4a96bd165.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-1-the-editor-view">1. The Editor View</h3>
<p>At first glance, it's a standard code editor. But it's deeply integrated with the AI. Beyond simple autocompletion, you can use natural language commands directly within your code files. For example, you can highlight a function and instruct the agent: <code>// @agent: refactor this function to be more efficient and add comments.</code></p>
<h3 id="heading-2-the-agent-view">2. The Agent View</h3>
<p>This is your command center for interacting with the AI. It's a chat-like interface where you provide high-level prompts. This is where you'll spend most of your time architecting.</p>
<p><strong>Example Prompt:</strong></p>
<pre><code class="lang-plaintext">Create a new React component called 'UserProfile'. It should accept a 'userId' prop, fetch user data from the '/api/users/{userId}' endpoint, and display the user's name and email. Include loading and error states. Also, generate a Storybook file for this component.
</code></pre>
<p>The agent will then outline its plan, ask for clarifications if needed, and begin implementation.</p>
<h3 id="heading-3-the-artifacts-view">3. The Artifacts View</h3>
<p>As the agent works, it generates <strong>Artifacts</strong>. These aren't just code files; they are live, interactive previews of the components, applications, or APIs it's building. If the agent is creating a React component, the Artifacts view will render it in a live environment, allowing you to see and interact with the result in real-time. This creates a tight feedback loop, enabling you to course-correct the agent instantly.</p>
<h2 id="heading-putting-antigravity-to-work-a-practical-walkthrough">Putting Antigravity to Work: A Practical Walkthrough</h2>
<p>Let's move from theory to practice. Heres how you might use Antigravity for common development tasks.</p>
<h3 id="heading-scenario-1-scaffolding-a-new-project">Scenario 1: Scaffolding a New Project</h3>
<p>Instead of manually running <code>create-next-app</code> and then adding dependencies like Prisma and Tailwind CSS, you can give the agent a single prompt.</p>
<p><strong>Prompt:</strong></p>
<blockquote>
<p>Scaffold a new Next.js 14 project with TypeScript. Integrate Tailwind CSS for styling and Prisma ORM for database access with a PostgreSQL database. Set up a basic project structure with a <code>components</code> and <code>lib</code> directory.</p>
</blockquote>
<p><strong>Result:</strong> The agent will execute all the necessary shell commands, configure the <code>tailwind.config.js</code> and <code>prisma/schema.prisma</code> files, and present you with a ready-to-use project structure, all in a fraction of the time it would take manually.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767260049793/e31e9eff-8db7-4a29-b3a9-a24bb922bf26.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-scenario-2-adding-a-feature-with-tdd">Scenario 2: Adding a Feature with TDD</h3>
<p>Antigravity excels at Test-Driven Development.</p>
<p><strong>Prompt:</strong></p>
<blockquote>
<p>I need a new utility function <code>isValidEmail(email: string)</code> in <code>lib/utils.ts</code>. First, write a comprehensive test suite for it using Jest, covering valid formats, invalid formats, and edge cases. Then, write the function to make all tests pass.</p>
</blockquote>
<p><strong>Result:</strong> The agent will first create <code>lib/utils.test.ts</code> with a full suite of tests, then implement <code>lib/utils.ts</code> to satisfy those tests, ensuring robust and well-tested code from the start.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Generated by Antigravity Agent</span>
<span class="hljs-comment">// lib/utils.ts</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> isValidEmail = (email: <span class="hljs-built_in">string</span>): <span class="hljs-function"><span class="hljs-params">boolean</span> =&gt;</span> {
  <span class="hljs-keyword">if</span> (!email || <span class="hljs-keyword">typeof</span> email !== <span class="hljs-string">'string'</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  }
  <span class="hljs-keyword">const</span> emailRegex = <span class="hljs-regexp">/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/</span>;
  <span class="hljs-keyword">return</span> emailRegex.test(email);
};
</code></pre>
<h3 id="heading-scenario-3-refactoring-legacy-code">Scenario 3: Refactoring Legacy Code</h3>
<p>We all have that one file we're afraid to touch. Antigravity can be a powerful ally in tackling technical debt.</p>
<p><strong>Prompt:</strong></p>
<blockquote>
<p>Analyze this legacy <code>api-handler.js</code> file. It's a large monolith with nested callbacks. Refactor it to use modern async/await syntax. Break down the core logic into smaller, single-responsibility functions. Ensure the public-facing API remains unchanged.</p>
</blockquote>
<p><strong>Result:</strong> The agent will analyze the data flow and dependencies within the file and propose a refactoring plan. Upon approval, it will rewrite the code, often with improved readability, maintainability, and performance.</p>
<h2 id="heading-advanced-capabilities-for-engineers">Advanced Capabilities for Engineers</h2>
<p>Antigravity's power extends far beyond basic coding tasks. Here's where it truly shines for experienced engineers:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767260008197/fa40a619-ef7e-456f-8ef2-b56b4b9e75cf.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-api-integration-and-code-generation">API Integration and Code Generation</h3>
<p>Give the agent an OpenAPI specification, and it can generate fully typed client-side code for fetching data [2]. This isn't just simple fetch wrappersit creates proper TypeScript interfaces, error handling, and even React hooks or query functions if you're using libraries like TanStack Query.</p>
<p><strong>Example Prompt:</strong></p>
<blockquote>
<p>I have an OpenAPI spec at <code>./api-spec.yaml</code>. Generate a fully typed TypeScript API client with fetch wrappers for all endpoints. Include proper error handling and retry logic.</p>
</blockquote>
<h3 id="heading-security-analysis-and-owasp-compliance">Security Analysis and OWASP Compliance</h3>
<p>Security is often an afterthought in rapid development. Antigravity can proactively audit your code [3].</p>
<p><strong>Example Prompt:</strong></p>
<blockquote>
<p>Audit this authentication module for common security vulnerabilities like XSS, SQL injection, CSRF, and insecure session management. Provide fixes based on OWASP Top 10 guidelines.</p>
</blockquote>
<p>The agent will scan your code, identify potential vulnerabilities, and suggest concrete fixes with code examples.</p>
<h3 id="heading-performance-tuning-and-profiling">Performance Tuning and Profiling</h3>
<p>Performance optimization often requires deep analysis. Antigravity can assist:</p>
<p><strong>Example Prompt:</strong></p>
<blockquote>
<p>Profile this data processing function. Identify performance bottlenecks, suggest algorithmic improvements, and rewrite it with better time complexity.</p>
</blockquote>
<p>The agent can analyze algorithmic complexity, suggest data structure improvements, and even rewrite functions to use more efficient patterns like memoization or lazy evaluation.</p>
<h3 id="heading-database-schema-design-and-migration">Database Schema Design and Migration</h3>
<p>Antigravity understands database design principles and can help with schema evolution:</p>
<p><strong>Example Prompt:</strong></p>
<blockquote>
<p>I need to add a many-to-many relationship between Users and Projects with additional metadata on the join table. Generate the Prisma schema changes and the migration file.</p>
</blockquote>
<p>The agent will create the proper schema definition, generate the migration, and even suggest indexes for optimal query performance.</p>
<h2 id="heading-understanding-the-limitations">Understanding the Limitations</h2>
<p>Antigravity is not without its limits. The current version has a <strong>5-hour continuous session limit</strong> for the agent [4], though Google's modeling suggests only a small fraction of power users will hit this threshold. For most developers, this is a non-issue. Google AI Pro and Ultra subscribers receive higher rate limits [5].</p>
<p>Other considerations:</p>
<ul>
<li><p><strong>Context Window:</strong> While Gemini 3 Pro has an impressive long-context window, extremely large monorepos may still require strategic prompting to keep the agent focused.</p>
</li>
<li><p><strong>Learning Curve:</strong> The shift from "doing" to "directing" requires a mental adjustment. You need to learn to communicate intent clearly and verify the agent's work.</p>
</li>
<li><p><strong>Verification Required:</strong> The agent is powerful but not infallible. Always review generated code, especially for security-critical or performance-sensitive sections.</p>
</li>
</ul>
<h2 id="heading-the-browser-extension-a-game-changer-for-frontend-work">The Browser Extension: A Game-Changer for Frontend Work</h2>
<p>One of the most exciting features is the <strong>Antigravity Browser Extension</strong> [6]. It allows you to use the agent to modify the UI of any live website directly from your browser.</p>
<p><strong>Use Cases:</strong></p>
<ul>
<li><p><strong>Rapid Prototyping:</strong> Point to an element and say, "Change the color of this button to blue," and the extension generates and applies the CSS instantly.</p>
</li>
<li><p><strong>Debugging:</strong> "Why is this element overflowing?" The agent can inspect the computed styles and suggest fixes.</p>
</li>
<li><p><strong>Accessibility Audits:</strong> "Check this page for accessibility issues" will trigger an automated audit with actionable recommendations.</p>
</li>
</ul>
<p>This is particularly powerful for frontend engineers who need to iterate quickly on design implementations or debug complex CSS issues in production environments.</p>
<h2 id="heading-real-world-impact-what-changes-for-engineers">Real-World Impact: What Changes for Engineers?</h2>
<p>After using Antigravity for several weeks, here's what fundamentally changes:</p>
<p><strong>Time Allocation Shifts:</strong></p>
<ul>
<li><p><strong>Less time on:</strong> Boilerplate code, configuration files, repetitive CRUD operations, basic bug fixes.</p>
</li>
<li><p><strong>More time on:</strong> System architecture, API design, performance optimization, security hardening, user experience.</p>
</li>
</ul>
<p><strong>Code Quality Improves:</strong></p>
<ul>
<li><p>The agent follows best practices by default (proper error handling, type safety, documentation).</p>
</li>
<li><p>Test coverage increases because generating tests is trivial.</p>
</li>
<li><p>Security vulnerabilities decrease due to proactive auditing.</p>
</li>
</ul>
<p><strong>Learning Accelerates:</strong></p>
<ul>
<li><p>You can ask the agent to explain its implementation choices.</p>
</li>
<li><p>It exposes you to patterns and libraries you might not have discovered otherwise.</p>
</li>
<li><p>It's like pair programming with an expert who never gets tired.</p>
</li>
</ul>
<h2 id="heading-getting-started-with-antigravity">Getting Started with Antigravity</h2>
<p>Ready to try it yourself? Here's how to get started:</p>
<ol>
<li><p><strong>Download:</strong> Visit <a target="_blank" href="http://antigravity.google/download">antigravity.google/download</a> to download the IDE for your platform (macOS, Windows, Linux).</p>
</li>
<li><p><strong>First-Time Setup:</strong> Follow the <a target="_blank" href="https://codelabs.developers.google.com/getting-started-google-antigravity">official getting started guide</a> [7].</p>
</li>
<li><p><strong>Start Small:</strong> Begin with simple prompts like "Create a utility function" before moving to complex multi-file features.</p>
</li>
<li><p><strong>Learn to Prompt:</strong> Effective prompting is key. Be specific about requirements, constraints, and desired patterns.</p>
</li>
<li><p><strong>Verify Everything:</strong> Always review the agent's work. It's a powerful assistant, not a replacement for engineering judgment.</p>
</li>
</ol>
<h2 id="heading-the-future-is-agentic">The Future is Agentic</h2>
<p>Google Antigravity is more than a tool; it's a glimpse into the future of software development. As Koray Kavukcuoglu, CTO of Google, stated, Antigravity is an effort to "push the frontiers of how the model and the IDE can work together" [8].</p>
<p>It challenges us to elevate our roles, to move from being bricklayers to architects. By automating the mundane, it allows us to focus on creativity, user experience, and the complex architectural challenges that truly require human ingenuity.</p>
<p>The transition may require a shift in mindset, but the potential for a massive leap in productivity and software quality is undeniable. The era of manually piloting your AI is quietly coming to an end [9]. The age of the agentic engineer is here.</p>
<p>Are you ready to make the shift?</p>
<hr />
<h3 id="heading-references">References</h3>
<ol>
<li><p><a target="_blank" href="https://developers.googleblog.com/build-with-google-antigravity-our-new-agentic-development-platform/">Google Developers Blog: Build with Google Antigravity, our new agentic development platform</a></p>
</li>
<li><p><a target="_blank" href="https://antigravity.google/docs">Google Antigravity Official Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://antigravity.google/docs/home">Google Antigravity Documentation - Security Features</a></p>
</li>
<li><p><a target="_blank" href="https://blog.google/feed/new-antigravity-rate-limits-pro-ultra-subsribers/">Google Blog: New Antigravity rate limits for Pro and Ultra subscribers</a></p>
</li>
<li><p><a target="_blank" href="https://blog.google/feed/new-antigravity-rate-limits-pro-ultra-subsribers/">Google Blog: Higher rate limits for AI Pro and Ultra subscribers</a></p>
</li>
<li><p><a target="_blank" href="https://antigravity.google/blog/introducing-google-antigravity">Google Antigravity Blog: Introducing Google Antigravity</a></p>
</li>
<li><p><a target="_blank" href="https://codelabs.developers.google.com/getting-started-google-antigravity">Codelabs: Getting Started with Google Antigravity</a></p>
</li>
<li><p><a target="_blank" href="https://www.constellationr.com/blog-news/insights/google-launches-gemini-3-google-antigravity-generative-ui-features">Constellation Research: Google launches Gemini 3, Google Antigravity, generative UI features</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@jengas/google-antigravity-deep-dive-a6895295f77f">Medium: Google Antigravity Deep Dive - Why the era of manually piloting your AI is quietly coming to an end</a></p>
</li>
</ol>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-01-01-1836</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-01-01-1836</guid><category><![CDATA[Google Antigravity]]></category><category><![CDATA[ AI Driven Development]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[developer productivity]]></category><category><![CDATA[Productivity]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Unlocking OmniFocus: A Guide to Secure Remote Access with Cloudflare Tunnel and MCP]]></title><description><![CDATA[<p><a target="_blank" href="https://www.omnigroup.com/omnifocus/">OmniFocus</a> is a powerhouse for task management, but its reliance on local access can feel restrictive in an era of cloud-native workflows. For engineers who live in the terminal and collaborate across distributed systems, the inability to programmatically interact with their task manager from anywhere is a significant bottleneck. What if you could bridge this gapsecurely, and without punching a single hole in your firewall?</p>
<p>This guide provides a comprehensive walkthrough for building a robust, secure, and persistent bridge between your always-on Mac running OmniFocus and a remote client like Claude Desktop. By leveraging the <strong>Model Context Protocol (MCP)</strong>, the excellent <a target="_blank" href="https://github.com/jqlts1/omnifocus-mcp-enhanced"><strong>omnifocus-mcp-enhanced</strong></a> [1] server, and the power of <strong>Cloudflare Tunnel</strong> [2], you can create a personal, AI-enabled productivity endpoint. We'll go beyond a simple proof-of-concept to build a production-ready setup that is both powerful and secure.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://speakerdeck.com/x5gtrn/remote-omnifocus-access-via-cloudflare-tunnel-plus-remote-mcp">https://speakerdeck.com/x5gtrn/remote-omnifocus-access-via-cloudflare-tunnel-plus-remote-mcp</a></div>
<p> </p>
<h2 id="heading-the-problem-omnifocus-in-a-cloud-first-world">The Problem: OmniFocus in a Cloud-First World</h2>
<p>OmniFocus is built on a philosophy of local-first data ownership, which is admirable from a privacy and control perspective. However, this design choice creates friction for modern workflows. Consider these scenarios:</p>
<ul>
<li><p>You're traveling without your Mac and need to quickly add a task based on a conversation.</p>
</li>
<li><p>You want to integrate OmniFocus with a CI/CD pipeline to automatically create tasks from failed builds.</p>
</li>
<li><p>You'd like to use AI assistants like Claude to intelligently query, filter, and organize your tasks using natural language.</p>
</li>
<li><p>You need to build custom dashboards or analytics on top of your task data.</p>
</li>
</ul>
<p>Traditional solutions like screen sharing or VNC are clunky and insecure. Cloud sync services like OmniSync solve device synchronization but don't provide programmatic access. This is where the <strong>Model Context Protocol</strong> comes in.</p>
<h2 id="heading-understanding-the-model-context-protocol-mcp">Understanding the Model Context Protocol (MCP)</h2>
<p>The Model Context Protocol is an open standard developed by Anthropic [3] that allows AI applications to securely connect to external data sources and tools. Think of it as a universal adapter that lets language models interact with your local services, databases, and applications in a structured, secure way.</p>
<p>MCP operates on a client-server model. The <strong>MCP server</strong> exposes a set of tools (functions) that can be invoked by an <strong>MCP client</strong> (like Claude Desktop). Communication happens via JSON-RPC, and the protocol supports both stdio (standard input/output) for local processes and HTTP/SSE (Server-Sent Events) for network communication.</p>
<p>The beauty of MCP is its simplicity and extensibility. By wrapping OmniFocus's AppleScript interface in an MCP server, we can expose rich task management capabilities to any MCP-compatible client, anywhere in the world.</p>
<h2 id="heading-the-architectural-blueprint-from-local-to-global">The Architectural Blueprint: From Local to Global</h2>
<p>At its core, our goal is to expose a local-only service to the internet securely. The architecture consists of three main layers:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767249220531/6084b501-3dbd-4e3d-8233-f7bfd0cfe524.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-layer-1-the-local-server-your-mac">Layer 1: The Local Server (Your Mac)</h3>
<p>This is the heart of the operation. It runs four key components:</p>
<ol>
<li><p><strong>OmniFocus Pro</strong>: The source of truth for your tasks. It must be running for the MCP server to interact with it via AppleScript.</p>
</li>
<li><p><strong>omnifocus-mcp-enhanced</strong>: A Node.js-based MCP server that translates MCP tool calls into AppleScript commands. It provides 16 tools, including task creation, querying, batch operations, and custom perspective access.</p>
</li>
<li><p><strong>mcp-remote</strong>: A proxy that converts the stdio-based MCP server into an HTTP/SSE endpoint. This is crucial because Cloudflare Tunnel works with HTTP services, not stdio.</p>
</li>
<li><p><strong>cloudflared</strong>: The Cloudflare Tunnel daemon that establishes a secure, outbound-only connection to the Cloudflare network.</p>
</li>
</ol>
<h3 id="heading-layer-2-the-cloud-layer-cloudflare">Layer 2: The Cloud Layer (Cloudflare)</h3>
<p>This is our secure bridge. Instead of opening inbound ports, the <code>cloudflared</code> daemon on your Mac creates a persistent, encrypted tunnel to the Cloudflare network. This tunnel is established via an outbound connection, which means:</p>
<ul>
<li><p><strong>No port forwarding</strong>: Your home router remains locked down.</p>
</li>
<li><p><strong>IP address masking</strong>: Your public IP is never exposed.</p>
</li>
<li><p><strong>DDoS protection</strong>: Cloudflare's network absorbs malicious traffic.</p>
</li>
<li><p><strong>Zero Trust access</strong>: You can layer on authentication and authorization policies.</p>
</li>
</ul>
<p>The tunnel is assigned a public hostname (e.g., <a target="_blank" href="http://omnifocus.yourdomain.com"><code>omnifocus.yourdomain.com</code></a>), which routes all HTTPS traffic through the encrypted tunnel back to your local server.</p>
<h3 id="heading-layer-3-the-remote-client-claude-desktop">Layer 3: The Remote Client (Claude Desktop)</h3>
<p>This is your interaction point. Claude Desktop (or any MCP-compatible client) communicates via standard HTTPS to the public hostname provided by Cloudflare. The client sends JSON-RPC requests, which are routed through the tunnel, converted by <code>mcp-remote</code>, and executed by the MCP server.</p>
<p>This model is fundamentally more secure than traditional port forwarding, as it never exposes your home network directly to the internet.</p>
<h2 id="heading-prerequisites-what-youll-need">Prerequisites: What You'll Need</h2>
<p>Before we begin, ensure you have the following in place:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Category</td><td>Requirement</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Hardware &amp; OS</strong></td><td>An always-on Mac (Intel or Apple Silicon) running macOS 11.0+</td></tr>
<tr>
<td><strong>Software</strong></td><td>OmniFocus Pro (v3+), Node.js (v18+), and a terminal client (e.g., iTerm2).</td></tr>
<tr>
<td><strong>Accounts</strong></td><td>A free Cloudflare account.</td></tr>
<tr>
<td><strong>Network</strong></td><td>Stable internet connection with outbound HTTPS access.</td></tr>
</tbody>
</table>
</div><p><strong>Why OmniFocus Pro?</strong> The Pro version is required for custom perspective access, which is one of the most powerful features of <code>omnifocus-mcp-enhanced</code>. Custom perspectives allow you to create highly specific views of your tasks (e.g., "all available tasks under 30 minutes with no dependencies"), and the MCP server can query these programmatically.</p>
<h2 id="heading-step-1-setting-up-the-omnifocus-mcp-server">Step 1: Setting Up the OmniFocus MCP Server</h2>
<p>The foundation of this setup is <code>omnifocus-mcp-enhanced</code>, a powerful Node.js server that acts as a bridge to OmniFocus's AppleScript interface. It exposes a rich set of tools for task management.</p>
<h3 id="heading-installation">Installation</h3>
<p>First, install it via npm. Using <code>npx</code> is a clean way to run it without global installation conflicts:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># This command adds the server to Claude's MCP list and runs it via npx</span>
claude mcp add omnifocus-enhanced -- npx -y omnifocus-mcp-enhanced
</code></pre>
<p>If you prefer a global installation for easier debugging:</p>
<pre><code class="lang-bash">npm install -g omnifocus-mcp-enhanced
claude mcp add omnifocus-enhanced -- omnifocus-mcp-enhanced
</code></pre>
<h3 id="heading-what-tools-does-it-provide">What Tools Does It Provide?</h3>
<p>The server exposes 16 tools across four categories:</p>
<p><strong>Database &amp; Task Management (8 tools):</strong></p>
<ul>
<li><p><code>dump_database</code>: Get the complete OmniFocus database state.</p>
</li>
<li><p><code>add_omnifocus_task</code>: Create tasks with full support for subtasks, due dates, tags, and notes.</p>
</li>
<li><p><code>add_project</code>: Create new projects.</p>
</li>
<li><p><code>remove_item</code>: Delete tasks or projects.</p>
</li>
<li><p><code>edit_item</code>: Modify existing tasks or projects.</p>
</li>
<li><p><code>batch_add_items</code>: Bulk create tasks and subtasks.</p>
</li>
<li><p><code>batch_remove_items</code>: Bulk delete items.</p>
</li>
<li><p><code>get_task_by_id</code>: Query specific task information.</p>
</li>
</ul>
<p><strong>Built-in Perspectives (5 tools):</strong></p>
<ul>
<li><p><code>get_inbox_tasks</code>: Access your Inbox.</p>
</li>
<li><p><code>get_flagged_tasks</code>: View all flagged tasks.</p>
</li>
<li><p><code>get_forecast_tasks</code>: See tasks due or deferred in the next N days.</p>
</li>
<li><p><code>get_tasks_by_tag</code>: Filter by tag name.</p>
</li>
<li><p><code>filter_tasks</code>: Advanced filtering with unlimited combinations (status, estimates, due dates, notes, etc.).</p>
</li>
</ul>
<p><strong>Custom Perspectives (2 tools - NEW):</strong></p>
<ul>
<li><p><code>list_custom_perspectives</code>: List all your custom perspectives.</p>
</li>
<li><p><code>get_custom_perspective_tasks</code>: Access a custom perspective with hierarchical task display.</p>
</li>
</ul>
<p><strong>Analytics (1 tool):</strong></p>
<ul>
<li><code>get_today_completed_tasks</code>: View today's completed tasks.</li>
</ul>
<h3 id="heading-testing-the-server">Testing the Server</h3>
<p>To verify the installation, you can test it locally. Run the server in stdio mode and send a JSON-RPC request:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">'{"jsonrpc":"2.0","id":1,"method":"get_inbox_tasks","params":{}}'</span> | npx omnifocus-mcp-enhanced
</code></pre>
<p>You should see a JSON response with your inbox tasks.</p>
<h2 id="heading-step-2-the-protocol-bridge-from-stdio-to-httpsse">Step 2: The Protocol Bridge - From Stdio to HTTP/SSE</h2>
<p>To make the stdio-based MCP server accessible over a network, we need a proxy. This proxy will listen for HTTP requests and translate them into stdio commands for the MCP server, then return the responses. We'll use <code>mcp-remote</code> for this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767249294492/d0af088e-5288-4919-8aff-b88e4f2899ca.jpeg" alt class="image--center mx-auto" /></p>
<p>This diagram illustrates the flow: a standard JSON-RPC request over stdio is wrapped into an HTTP POST request, and the response is streamed back via Server-Sent Events (SSE). SSE is ideal for this use case because it allows the server to push updates to the client in real-time, which is useful for long-running operations or streaming responses.</p>
<h3 id="heading-installing-mcp-remote">Installing mcp-remote</h3>
<p>First, install <code>mcp-remote</code> globally:</p>
<pre><code class="lang-bash">npm install -g mcp-remote
</code></pre>
<h3 id="heading-running-the-proxy">Running the Proxy</h3>
<p>Run the following command in your terminal. This tells <code>mcp-remote</code> to act as a proxy, listening on port 3000 and forwarding all communication to our <code>omnifocus-mcp-enhanced</code> server process.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Start the proxy server on port 3000</span>
mcp-remote --stdio <span class="hljs-string">"npx omnifocus-mcp-enhanced"</span> --port 3000
</code></pre>
<p>At this point, you have a local HTTP server running on <a target="_blank" href="http://localhost:3000"><code>http://localhost:3000</code></a> that can control OmniFocus. You can test this with <code>curl</code>:</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> \
  -d <span class="hljs-string">'{"jsonrpc":"2.0","id":1,"method":"get_inbox_tasks","params":{}}'</span> \
  http://localhost:3000
</code></pre>
<p>You should receive a JSON response with your inbox tasks. This confirms that the protocol conversion is working correctly.</p>
<h3 id="heading-understanding-the-data-flow">Understanding the Data Flow</h3>
<p>Let's break down what happens when you make a request:</p>
<ol>
<li><p><strong>Client sends HTTP POST</strong>: The client (e.g., Claude Desktop) sends a JSON-RPC request to <a target="_blank" href="http://localhost:3000"><code>http://localhost:3000</code></a>.</p>
</li>
<li><p><strong>mcp-remote receives the request</strong>: The proxy parses the HTTP body and extracts the JSON-RPC payload.</p>
</li>
<li><p><strong>Proxy forwards to stdio</strong>: The proxy writes the JSON-RPC request to the stdin of the <code>omnifocus-mcp-enhanced</code> process.</p>
</li>
<li><p><strong>MCP server executes</strong>: The server parses the request, executes the corresponding AppleScript, and writes the result to stdout.</p>
</li>
<li><p><strong>Proxy reads stdout</strong>: The proxy reads the JSON-RPC response from stdout.</p>
</li>
<li><p><strong>Proxy sends HTTP response</strong>: The proxy wraps the response in an HTTP 200 OK with <code>Content-Type: text/event-stream</code> and streams it back to the client via SSE.</p>
</li>
</ol>
<p>This design is elegant because it maintains the simplicity of stdio for local communication while enabling network access.</p>
<h2 id="heading-step-3-building-the-secure-tunnel-with-cloudflare">Step 3: Building the Secure Tunnel with Cloudflare</h2>
<p>Now, we'll expose our local server to the internet without opening any ports. This is where Cloudflare Tunnel shines.</p>
<h3 id="heading-why-cloudflare-tunnel">Why Cloudflare Tunnel?</h3>
<p>Traditional remote access methods have significant drawbacks:</p>
<ul>
<li><p><strong>Port forwarding</strong>: Exposes your home IP and requires router configuration. Vulnerable to attacks.</p>
</li>
<li><p><strong>VPN</strong>: Requires client-side setup and can be complex to manage.</p>
</li>
<li><p><strong>ngrok/localtunnel</strong>: Great for testing, but free tiers have limitations and URLs change frequently.</p>
</li>
</ul>
<p>Cloudflare Tunnel solves these problems by creating a secure, persistent, outbound-only connection from your Mac to Cloudflare's network. Traffic is routed through Cloudflare's global edge, which provides DDoS protection, caching, and Zero Trust access controlsall on the free tier.</p>
<h3 id="heading-installation-and-setup">Installation and Setup</h3>
<ol>
<li><p><strong>Install</strong> <code>cloudflared</code>: If you don't have it, install the daemon using Homebrew:</p>
<pre><code class="lang-bash"> brew install cloudflared
</code></pre>
</li>
<li><p><strong>Authenticate</strong>: Log in to your Cloudflare account. This will open a browser window for authentication.</p>
<pre><code class="lang-bash"> cloudflared tunnel login
</code></pre>
<p> After successful login, a certificate file is saved to <code>~/.cloudflared/cert.pem</code>.</p>
</li>
<li><p><strong>Create a Tunnel</strong>: Give your tunnel a memorable name.</p>
<pre><code class="lang-bash"> cloudflared tunnel create omnifocus-mcp
</code></pre>
<p> This will generate:</p>
<ul>
<li><p>A UUID for your tunnel (e.g., <code>abc123-def456-ghi789</code>).</p>
</li>
<li><p>A credentials file at <code>~/.cloudflared/&lt;UUID&gt;.json</code>.</p>
</li>
</ul>
</li>
</ol>
<p>    Save the UUIDyou'll need it for the configuration file.</p>
<ol start="4">
<li><p><strong>Configure the Tunnel</strong>: Create a <code>config.yml</code> file in <code>~/.cloudflared/</code>. This file tells the daemon how to route traffic.</p>
<pre><code class="lang-yaml"> <span class="hljs-attr">tunnel:</span> <span class="hljs-string">abc123-def456-ghi789</span>  <span class="hljs-comment"># Replace with your tunnel UUID</span>
 <span class="hljs-attr">credentials-file:</span> <span class="hljs-string">/Users/yourname/.cloudflared/abc123-def456-ghi789.json</span>

 <span class="hljs-attr">ingress:</span>
   <span class="hljs-comment"># Route traffic from omnifocus.yourdomain.com to localhost:3000</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">hostname:</span> <span class="hljs-string">omnifocus.yourdomain.com</span>
     <span class="hljs-attr">service:</span> <span class="hljs-string">http://localhost:3000</span>
   <span class="hljs-comment"># Catch-all rule to prevent unconfigured hostnames from exposing your service</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">service:</span> <span class="hljs-string">http_status:404</span>
</code></pre>
<p> The <code>ingress</code> rules define how traffic is routed. The first rule matches the hostname and forwards to your local service. The catch-all rule returns a 404 for any other hostname, which prevents accidental exposure.</p>
</li>
<li><p><strong>Route DNS</strong>: Link your tunnel to a public DNS record. This command creates a CNAME record in your Cloudflare DNS that points to the tunnel.</p>
<pre><code class="lang-bash"> cloudflared tunnel route dns omnifocus-mcp omnifocus.yourdomain.com
</code></pre>
</li>
<li><p><strong>Run the Tunnel</strong>: Start the tunnel to begin proxying traffic.</p>
<pre><code class="lang-bash"> cloudflared tunnel run omnifocus-mcp
</code></pre>
<p> You should see output indicating the tunnel is connected:</p>
<pre><code class="lang-plaintext"> 2025-01-01T12:00:00Z INF Connection registered connIndex=0 location=SFO
 2025-01-01T12:00:00Z INF Registered tunnel connection connIndex=0 location=SFO
</code></pre>
</li>
</ol>
<p>Your local server on port 3000 is now securely accessible at <a target="_blank" href="https://omnifocus.yourdomain.com"><code>https://omnifocus.yourdomain.com</code></a>!</p>
<h3 id="heading-testing-the-tunnel">Testing the Tunnel</h3>
<p>From any device with internet access, test the tunnel:</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> \
  -d <span class="hljs-string">'{"jsonrpc":"2.0","id":1,"method":"get_inbox_tasks","params":{}}'</span> \
  https://omnifocus.yourdomain.com
</code></pre>
<p>You should receive your inbox tasks, confirming that the entire pipeline is working.</p>
<h2 id="heading-step-4-configuring-the-remote-client">Step 4: Configuring the Remote Client</h2>
<p>With the tunnel active, the final step is to tell your remote client (Claude Desktop) how to connect. Claude Desktop uses a configuration file to define MCP servers.</p>
<h3 id="heading-locating-the-configuration-file">Locating the Configuration File</h3>
<p>The configuration file is located at:</p>
<ul>
<li><p><strong>macOS</strong>: <code>~/Library/Application Support/Claude/claude_desktop_config.json</code></p>
</li>
<li><p><strong>Windows</strong>: <code>%APPDATA%\Claude\claude_desktop_config.json</code></p>
</li>
</ul>
<h3 id="heading-adding-the-server">Adding the Server</h3>
<p>Edit the file to add your remote MCP server:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"omnifocus"</span>: {
      <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://omnifocus.yourdomain.com"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"http"</span>
    }
  }
}
</code></pre>
<h3 id="heading-restarting-claude-desktop">Restarting Claude Desktop</h3>
<p>Restart Claude Desktop to load the new configuration. You should now see "omnifocus" listed in the MCP servers section.</p>
<h3 id="heading-testing-the-integration">Testing the Integration</h3>
<p>Open a conversation in Claude and try a command:</p>
<pre><code class="lang-plaintext">Can you show me my inbox tasks?
</code></pre>
<p>Claude will invoke the <code>get_inbox_tasks</code> tool and display the results. You can also try more complex queries:</p>
<pre><code class="lang-plaintext">Create a task called "Review Q1 metrics" in the "Work" project, due next Friday, with a 2-hour estimate.
</code></pre>
<p>Claude will parse your natural language request and call the appropriate MCP tool with the correct parameters.</p>
<h2 id="heading-step-5-ensuring-persistence-with-launchd">Step 5: Ensuring Persistence with <code>launchd</code></h2>
<p>For a truly "always-on" experience, you need the <code>mcp-remote</code> proxy and the <code>cloudflared</code> tunnel to run continuously and restart automatically. On macOS, <code>launchd</code> is the perfect tool for this.</p>
<h3 id="heading-creating-a-launchd-service-for-mcp-remote">Creating a <code>launchd</code> Service for mcp-remote</h3>
<ol>
<li><p><strong>Create the</strong> <code>.plist</code> file: Save this to <code>~/Library/LaunchAgents/com.omnifocus.mcp.proxy.plist</code>.</p>
<pre><code class="lang-xml"> <span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
 <span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">plist</span> <span class="hljs-meta-keyword">PUBLIC</span> <span class="hljs-meta-string">"-//Apple//DTD PLIST 1.0//EN"</span> <span class="hljs-meta-string">"http://www.apple.com/DTDs/PropertyList-1.0.dtd"</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">plist</span> <span class="hljs-attr">version</span>=<span class="hljs-string">"1.0"</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">dict</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>Label<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>com.omnifocus.mcp.proxy<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>ProgramArguments<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">array</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>/usr/local/bin/mcp-remote<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>--stdio<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>npx omnifocus-mcp-enhanced<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>--port<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>3000<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">array</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>RunAtLoad<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">true</span>/&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>KeepAlive<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">true</span>/&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>StandardOutPath<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>/tmp/mcp-remote.log<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">key</span>&gt;</span>StandardErrorPath<span class="hljs-tag">&lt;/<span class="hljs-name">key</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">string</span>&gt;</span>/tmp/mcp-remote.error.log<span class="hljs-tag">&lt;/<span class="hljs-name">string</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">dict</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">plist</span>&gt;</span>
</code></pre>
<p> <strong>Key fields:</strong></p>
<ul>
<li><p><code>Label</code>: Unique identifier for the service.</p>
</li>
<li><p><code>ProgramArguments</code>: The command to run. Update <code>/usr/local/bin/mcp-remote</code> to the actual path (find it with <code>which mcp-remote</code>).</p>
</li>
<li><p><code>RunAtLoad</code>: Start the service when the user logs in.</p>
</li>
<li><p><code>KeepAlive</code>: Restart the service if it crashes.</p>
</li>
<li><p><code>StandardOutPath</code> and <code>StandardErrorPath</code>: Log files for debugging.</p>
</li>
</ul>
</li>
<li><p><strong>Load the service</strong>:</p>
<pre><code class="lang-bash"> launchctl load ~/Library/LaunchAgents/com.omnifocus.mcp.proxy.plist
</code></pre>
</li>
<li><p><strong>Verify it's running</strong>:</p>
<pre><code class="lang-bash"> launchctl list | grep omnifocus
</code></pre>
<p> You should see the service listed with a PID.</p>
</li>
</ol>
<h3 id="heading-creating-a-launchd-service-for-cloudflared">Creating a <code>launchd</code> Service for cloudflared</h3>
<p>Cloudflare provides a built-in command to install the tunnel as a service:</p>
<pre><code class="lang-bash">sudo cloudflared service install
</code></pre>
<p>This creates a system-level <code>launchd</code> service that runs at boot. To start it immediately:</p>
<pre><code class="lang-bash">sudo launchctl start com.cloudflare.cloudflared
</code></pre>
<h3 id="heading-handling-macos-sleep">Handling macOS Sleep</h3>
<p>One challenge with always-on services on macOS is sleep management. If your Mac goes to sleep, the tunnel will disconnect. To prevent this, you can:</p>
<ol>
<li><p><strong>Disable sleep</strong>: Go to <strong>System Preferences &gt; Energy Saver</strong> and set "Prevent your Mac from automatically sleeping when the display is off."</p>
</li>
<li><p><strong>Use</strong> <code>caffeinate</code>: Run <code>caffeinate -s</code> to prevent sleep while the terminal is open.</p>
</li>
<li><p><strong>Use a third-party tool</strong>: Apps like Amphetamine can prevent sleep based on custom rules.</p>
</li>
</ol>
<p>For a true server setup, consider running this on a Mac Mini or an old MacBook with the lid closed and power management configured for 24/7 operation.</p>
<h2 id="heading-real-world-use-cases">Real-World Use Cases</h2>
<p>Now that your setup is live, what can you do with it? Here are some practical examples:</p>
<h3 id="heading-1-ai-powered-task-triage">1. AI-Powered Task Triage</h3>
<p>Use Claude to intelligently filter and prioritize your tasks:</p>
<pre><code class="lang-plaintext">Show me all available tasks under 30 minutes that are due this week, sorted by project.
</code></pre>
<p>Claude will call the <code>filter_tasks</code> tool with the appropriate parameters and present a clean, organized list.</p>
<h3 id="heading-2-automated-task-creation-from-external-systems">2. Automated Task Creation from External Systems</h3>
<p>Integrate with webhooks or CI/CD pipelines to automatically create tasks. For example, when a GitHub issue is assigned to you, a webhook can POST to your MCP server:</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> \
  -d <span class="hljs-string">'{"jsonrpc":"2.0","id":1,"method":"add_omnifocus_task","params":{"name":"Fix bug #123","projectName":"Engineering","tags":["bug","urgent"]}}'</span> \
  https://omnifocus.yourdomain.com
</code></pre>
<h3 id="heading-3-custom-dashboards">3. Custom Dashboards</h3>
<p>Build a web dashboard that queries your OmniFocus data via the MCP server. You could visualize:</p>
<ul>
<li><p>Tasks completed per day/week.</p>
</li>
<li><p>Time estimates vs. actuals.</p>
</li>
<li><p>Project progress.</p>
</li>
</ul>
<h3 id="heading-4-voice-activated-task-management">4. Voice-Activated Task Management</h3>
<p>Combine this setup with a voice assistant (e.g., Siri Shortcuts or a custom Alexa skill) to add tasks hands-free.</p>
<h3 id="heading-5-cross-platform-access">5. Cross-Platform Access</h3>
<p>Since the MCP server is now accessible via HTTPS, you can build clients for any platformiOS, Android, web, or even a command-line tool.</p>
<h2 id="heading-a-multi-layered-security-approach">A Multi-Layered Security Approach</h2>
<p>This architecture is secure by design, but you can harden it further.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767249340105/29335392-7338-444a-85cd-0e8512aacb53.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-layer-1-cloudflare-ddos-protection">Layer 1: Cloudflare DDoS Protection</h3>
<p>Cloudflare's network automatically mitigates large-scale traffic floods and volumetric attacks, ensuring your service remains available even under attack.</p>
<h3 id="heading-layer-2-httpstls-encryption">Layer 2: HTTPS/TLS Encryption</h3>
<p>All traffic between the client and Cloudflare, and between Cloudflare and your Mac, is encrypted using TLS. This prevents eavesdropping and tampering.</p>
<h3 id="heading-layer-3-zero-trust-access">Layer 3: Zero Trust Access</h3>
<p>Cloudflare Access allows you to add an authentication layer before any traffic reaches your tunnel. You can require users to log in with Google, GitHub, or any OIDC provider. You can also restrict access to specific IP ranges or countries.</p>
<p>To enable Cloudflare Access:</p>
<ol>
<li><p>Go to <strong>Cloudflare Dashboard &gt; Zero Trust &gt; Access &gt; Applications</strong>.</p>
</li>
<li><p>Click <strong>Add an Application</strong> and select <strong>Self-hosted</strong>.</p>
</li>
<li><p>Set the application domain to <a target="_blank" href="http://omnifocus.yourdomain.com"><code>omnifocus.yourdomain.com</code></a>.</p>
</li>
<li><p>Configure an access policy (e.g., "Allow emails ending in @<a target="_blank" href="http://yourcompany.com">yourcompany.com</a>").</p>
</li>
</ol>
<p>Now, anyone trying to access your MCP server will be prompted to authenticate first.</p>
<h3 id="heading-layer-4-api-key-management">Layer 4: API Key Management</h3>
<p>For production use, consider forking the <code>omnifocus-mcp-enhanced</code> server to add a simple API key check. You can pass the key as a header:</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> \
  -H <span class="hljs-string">"X-API-Key: your-secret-key"</span> \
  -d <span class="hljs-string">'{"jsonrpc":"2.0","id":1,"method":"get_inbox_tasks","params":{}}'</span> \
  https://omnifocus.yourdomain.com
</code></pre>
<p>The server can validate the key before processing the request.</p>
<h3 id="heading-layer-5-local-firewall">Layer 5: Local Firewall</h3>
<p>Ensure your Mac's firewall is enabled and only allows outbound connections. Since the tunnel is outbound-only, you don't need to open any inbound ports.</p>
<h3 id="heading-monitoring-and-logging">Monitoring and Logging</h3>
<p>Regularly review the Cloudflare dashboard for traffic patterns and potential threats. The <code>launchd</code> service logs (<code>/tmp/mcp-remote.log</code>) can help you debug issues and monitor usage.</p>
<h2 id="heading-troubleshooting-common-issues">Troubleshooting Common Issues</h2>
<h3 id="heading-issue-1-tunnel-not-connecting">Issue 1: Tunnel Not Connecting</h3>
<p><strong>Symptoms</strong>: <code>cloudflared tunnel run</code> fails with "connection refused" or "authentication failed."</p>
<p><strong>Solutions</strong>:</p>
<ul>
<li><p>Verify your credentials file path in <code>config.yml</code>.</p>
</li>
<li><p>Ensure you're logged in with <code>cloudflared tunnel login</code>.</p>
</li>
<li><p>Check that the tunnel UUID in <code>config.yml</code> matches the one created.</p>
</li>
</ul>
<h3 id="heading-issue-2-mcp-server-not-responding">Issue 2: MCP Server Not Responding</h3>
<p><strong>Symptoms</strong>: Requests to the tunnel return 502 Bad Gateway.</p>
<p><strong>Solutions</strong>:</p>
<ul>
<li><p>Verify <code>mcp-remote</code> is running on port 3000 with <code>lsof -i :3000</code>.</p>
</li>
<li><p>Check the logs at <code>/tmp/mcp-remote.log</code> for errors.</p>
</li>
<li><p>Ensure OmniFocus is running.</p>
</li>
</ul>
<h3 id="heading-issue-3-claude-desktop-not-seeing-the-server">Issue 3: Claude Desktop Not Seeing the Server</h3>
<p><strong>Symptoms</strong>: The "omnifocus" server doesn't appear in Claude Desktop.</p>
<p><strong>Solutions</strong>:</p>
<ul>
<li><p>Verify the <code>claude_desktop_config.json</code> syntax is correct (valid JSON).</p>
</li>
<li><p>Restart Claude Desktop completely (quit and reopen).</p>
</li>
<li><p>Check that the URL in the config is accessible from your current network.</p>
</li>
</ul>
<h3 id="heading-issue-4-slow-response-times">Issue 4: Slow Response Times</h3>
<p><strong>Symptoms</strong>: Requests take several seconds to complete.</p>
<p><strong>Solutions</strong>:</p>
<ul>
<li><p>Check your internet connection speed.</p>
</li>
<li><p>Verify the Cloudflare edge location is geographically close to you.</p>
</li>
<li><p>Profile the AppleScript execution timecomplex queries can be slow.</p>
</li>
</ul>
<h2 id="heading-advanced-optimizations">Advanced Optimizations</h2>
<h3 id="heading-caching-responses">Caching Responses</h3>
<p>For read-heavy operations (e.g., querying tasks), you can add a caching layer using Redis or a simple in-memory cache in the <code>mcp-remote</code> proxy. This reduces the load on OmniFocus and speeds up responses.</p>
<h3 id="heading-load-balancing">Load Balancing</h3>
<p>If you have multiple Macs, you can run the MCP server on each and use Cloudflare Load Balancing to distribute traffic. This provides redundancy and higher availability.</p>
<h3 id="heading-custom-tools">Custom Tools</h3>
<p>The <code>omnifocus-mcp-enhanced</code> server is open source, so you can fork it and add custom tools. For example, you could add a tool to export tasks to CSV, or integrate with external APIs (e.g., send a Slack notification when a task is completed).</p>
<h2 id="heading-conclusion-your-productivity-unleashed">Conclusion: Your Productivity, Unleashed</h2>
<p>By combining the power of local AppleScript automation with the secure, global reach of Cloudflare, you've effectively transformed OmniFocus into a cloud-aware service. This setup not only enables remote task management but also opens the door to more complex AI-driven workflows, custom integrations, and a truly sovereign productivity system.</p>
<p>The architecture we've built is production-ready, secure, and extensible. You've learned how to:</p>
<ul>
<li><p>Expose a local stdio-based service over HTTP using <code>mcp-remote</code>.</p>
</li>
<li><p>Create a secure, persistent tunnel with Cloudflare without opening any ports.</p>
</li>
<li><p>Integrate with Claude Desktop for natural language task management.</p>
</li>
<li><p>Ensure 24/7 uptime with <code>launchd</code> services.</p>
</li>
<li><p>Implement multi-layered security with Zero Trust access and encryption.</p>
</li>
</ul>
<p>This is just the beginning. With this foundation, you can build custom clients, integrate with other tools, and create a productivity ecosystem that works exactly the way you want it to. The power of OmniFocus is no longer confined to your Macit's now accessible from anywhere, securely and seamlessly.</p>
<hr />
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://github.com/jqlts1/omnifocus-mcp-enhanced">omnifocus-mcp-enhanced GitHub Repository</a></p>
</li>
<li><p><a target="_blank" href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/">Cloudflare Tunnel Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://modelcontextprotocol.io/">Model Context Protocol Overview</a></p>
</li>
<li><p><a target="_blank" href="https://developers.cloudflare.com/cloudflare-one/policies/access/">Cloudflare Zero Trust Access</a></p>
</li>
<li><p><a target="_blank" href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html">Apple launchd Documentation</a></p>
</li>
</ol>
]]></description><link>https://daisuke.masuda.tokyo/article-2026-01-01-1540</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2026-01-01-1540</guid><category><![CDATA[mcp]]></category><category><![CDATA[mcp server]]></category><category><![CDATA[MCP Client]]></category><category><![CDATA[claude]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[AI]]></category><category><![CDATA[task management]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[From Java to Kotlin: A Pragmatic Guide to Modernizing Your Server-Side Codebase]]></title><description><![CDATA[<p>For decades, Java has been the undisputed titan of server-side development, powering everything from monolithic enterprise systems to nimble microservices. Its robust, mature, and backed by a colossal ecosystem. But in the fast-paced world of software engineering, whats dominant today isnt always whats best for tomorrow. The question for modern engineering teams is no longer just Can Java do it? but Is there a better way?</p>
<p><strong>Enter Kotlin.</strong></p>
<p>Created by JetBrains and officially endorsed by Google for Android development, Kotlin has rapidly matured into a formidable contender on the server side. Its not a radical replacement for Java but a pragmatic, modern evolution. It runs on the JVM, interoperates seamlessly with Java, and addresses many of the pain points that have frustrated Java developers for years.</p>
<p>This article is a deep dive for engineers, by an engineer. Well move beyond the hype and explore the concrete reasons <strong>why</strong> you should consider Kotlin, <strong>how</strong> to approach a migration strategically, and <strong>what to expect</strong> along the way. Whether youre a junior developer learning the ropes or a senior architect planning your companys next tech stack, this guide will provide the practical insights you need.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://speakerdeck.com/x5gtrn/from-java-to-kotlin-modernizing-server-side-development">https://speakerdeck.com/x5gtrn/from-java-to-kotlin-modernizing-server-side-development</a></div>
<p> </p>
<hr />
<h2 id="heading-the-why-4-compelling-reasons-to-switch-to-kotlin">The Why: 4 Compelling Reasons to Switch to Kotlin</h2>
<p>Change for the sake of change is a recipe for disaster. A language migration must be justified by tangible benefits that improve code quality, developer productivity, and system reliability. Here are the four pillars of Kotlins value proposition on the server side.</p>
<h3 id="heading-1-null-safety-slaying-the-billion-dollar-mistake">1. Null Safety: Slaying the Billion-Dollar Mistake</h3>
<p>If youve written Java, youve written <code>if (obj != null)</code>. Youve also probably been haunted by the infamous <code>NullPointerException</code> (NPE). Its creator, Tony Hoare, famously called it his billion-dollar mistake. Its a runtime error that occurs because Javas type system allows any reference to be <code>null</code>, and the compiler offers no help in preventing you from using it unsafely.</p>
<p>Kotlin tackles this head-on by baking nullability directly into its type system. This is arguably its single most important feature.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766970557904/f11e41bd-296c-4fed-8882-50fd0dbb3f5e.jpeg" alt class="image--center mx-auto" /></p>
<p>In Kotlin, types are non-nullable by default. If you want a variable to hold <code>null</code>, you must explicitly declare it as a nullable type by adding a <code>?</code> suffix.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">var</span> a: String = <span class="hljs-string">"abc"</span> <span class="hljs-comment">// Non-nullable</span>
a = <span class="hljs-literal">null</span> <span class="hljs-comment">// Compilation error!</span>

<span class="hljs-keyword">var</span> b: String? = <span class="hljs-string">"abc"</span> <span class="hljs-comment">// Nullable</span>
b = <span class="hljs-literal">null</span> <span class="hljs-comment">// OK</span>
</code></pre>
<p>This simple distinction moves null-related errors from runtime crashes to compile-time failures. The compiler forces you to handle nullable types safely before you can use them, using tools like:</p>
<ul>
<li><p><strong>Safe Calls (</strong><code>?.</code>): Executes the call only if the value is not null; otherwise, it returns <code>null</code>.</p>
</li>
<li><p><strong>The Elvis Operator (</strong><code>?:</code>): Provides a default value if the expression on the left is <code>null</code>.</p>
</li>
</ul>
<pre><code class="lang-kotlin"><span class="hljs-comment">// Java (defensive coding)</span>
String value = mightBeNull();
int length = <span class="hljs-number">0</span>;
<span class="hljs-keyword">if</span> (value != <span class="hljs-literal">null</span>) {
    length = value.length();
}

<span class="hljs-comment">// Kotlin (idiomatic and safe)</span>
<span class="hljs-keyword">val</span> value: String? = mightBeNull()
<span class="hljs-keyword">val</span> length = value?.length ?: <span class="hljs-number">0</span> <span class="hljs-comment">// One line, guaranteed safe</span>
</code></pre>
<p>For server-side applications where uptime and reliability are paramount, eliminating an entire class of runtime exceptions is a massive win.</p>
<h3 id="heading-2-conciseness-and-readability-write-less-do-more">2. Conciseness and Readability: Write Less, Do More</h3>
<p>Java is notoriously verbose. A simple data-holding class (a POJO) requires hundreds of lines of boilerplate for constructors, getters, setters, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code>. This isnt just an aesthetic issue; excessive boilerplate obscures business logic and creates more opportunities for bugs.</p>
<p>Kotlin drastically reduces this verbosity with features like <strong>data classes</strong>.</p>
<p><strong>Java POJO:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> age;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object o)</span> </span>{ ... }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span> </span>{ ... }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{ ... }
}
</code></pre>
<p><strong>Kotlin Data Class:</strong></p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>(<span class="hljs-keyword">val</span> name: String, <span class="hljs-keyword">val</span> age: <span class="hljs-built_in">Int</span>)
</code></pre>
<p>That one line of Kotlin generates a class with a constructor, properties (<code>name</code>, <code>age</code>), getters, and sensible <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> implementations. This lets you focus on your domain model, not on ceremonial code.</p>
<p>Other features like <strong>type inference</strong>, <strong>smart casts</strong>, and <strong>extension functions</strong> further contribute to cleaner, more expressive code. For example, an extension function lets you add new functionality to an existing class without inheriting from it.</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> String.<span class="hljs-title">toSlug</span><span class="hljs-params">()</span></span>: String {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.toLowerCase().replace(<span class="hljs-string">" "</span>, <span class="hljs-string">"-"</span>)
}

<span class="hljs-comment">// Now you can call it on any String!</span>
<span class="hljs-keyword">val</span> blogTitle = <span class="hljs-string">"My Awesome Post"</span>
<span class="hljs-keyword">val</span> slug = blogTitle.toSlug() <span class="hljs-comment">// "my-awesome-post"</span>
</code></pre>
<p>This expressiveness leads to codebases that are easier to read, maintain, and reason abouta critical advantage in complex server-side systems.</p>
<h3 id="heading-3-coroutines-lightweight-concurrency-for-the-modern-server">3. Coroutines: Lightweight Concurrency for the Modern Server</h3>
<p>Traditional server-side concurrency in Java relies on a thread-per-request model. While effective, threads are heavyweight operating system resources. A server can only handle a few thousand active threads before performance degrades due to memory consumption and context-switching overhead. This becomes a bottleneck in applications with high I/O latency, like microservices that call other services.</p>
<p>Kotlin introduces <strong>coroutines</strong>, a paradigm for structured concurrency. Coroutines are incredibly lightweightyou can run tens of thousands, even millions, on a single thread without breaking a sweat. They allow you to write asynchronous, non-blocking code in a simple, sequential style.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766970612991/b6477dbc-56e9-45af-a2f0-1c178539c7a7.jpeg" alt class="image--center mx-auto" /></p>
<p>Consider a simple task: fetching user data and their orders from two different services.</p>
<p><strong>Traditional Threads (Blocking):</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Each call blocks a thread, wasting resources while waiting for the network</span>
User user = userApi.fetchUser(userId);
List&lt;Order&gt; orders = orderApi.fetchOrders(user.getId());
</code></pre>
<p><strong>Kotlin Coroutines (Non-Blocking):</strong></p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getUserProfile</span><span class="hljs-params">(userId: <span class="hljs-type">String</span>)</span></span>: Profile {
    <span class="hljs-comment">// The `async` block starts a coroutine</span>
    <span class="hljs-keyword">val</span> userDeferred = coroutineScope { async { userApi.fetchUser(userId) } }
    <span class="hljs-keyword">val</span> ordersDeferred = coroutineScope { async { orderApi.fetchOrders(userId) } }

    <span class="hljs-comment">// `await()` suspends the function without blocking the thread</span>
    <span class="hljs-keyword">val</span> user = userDeferred.await()
    <span class="hljs-keyword">val</span> orders = ordersDeferred.await()

    <span class="hljs-keyword">return</span> Profile(user, orders)
}
</code></pre>
<p>The <code>suspend</code> keyword marks a function that can be paused and resumed later. While its waiting for the network calls to complete, the underlying thread is freed up to do other work. This model, often called asynchronous but sequential, provides the scalability of reactive programming without the cognitive overhead of callback chains or complex libraries like RxJava.</p>
<p>Frameworks like <a target="_blank" href="https://spring.io/blog/2022/05/24/preparing-for-spring-boot-3-0">Spring Boot 6</a> and Ktor have first-class support for coroutines, making it easy to build highly scalable, non-blocking APIs.</p>
<h3 id="heading-4-100-java-interoperability-a-no-risk-proposition">4. 100% Java Interoperability: A No-Risk Proposition</h3>
<p>Perhaps the most compelling reason for adoption is that Kotlin is not an all-or-nothing choice. It is <strong>100% interoperable with Java</strong>. This means:</p>
<ul>
<li><p>You can call Java code from Kotlin, and Kotlin code from Java.</p>
</li>
<li><p>You can have Java and Kotlin classes side-by-side in the same project.</p>
</li>
<li><p>You can continue using all your existing Java libraries and frameworks (Spring, Hibernate, etc.).</p>
</li>
</ul>
<p>This seamless interoperability de-risks the migration process entirely. You dont need a massive, flag-day rewrite. Instead, you can adopt Kotlin gradually.</p>
<blockquote>
<p>We found that developers migrated Java code to Kotlin in order to access programming language features (eg, extension functions, lambdas, smart casts) - <a target="_blank" href="https://arxiv.org/abs/2003.12730">Why did developers migrate Android applications from Java to Kotlin?</a></p>
</blockquote>
<p>This is a strategy that has been proven at massive scale. Companies like <a target="_blank" href="https://engineering.fb.com/2022/10/24/android/android-java-kotlin-migration/">Meta</a> and <a target="_blank" href="https://kotlinconf.com/talks/811915/">Uber</a> have migrated millions of lines of code from Java to Kotlin incrementally, file by file, without disrupting their development cycles.</p>
<hr />
<h2 id="heading-the-how-a-practical-roadmap-for-migration">The How: A Practical Roadmap for Migration</h2>
<p>So, youre convinced. But where do you start? A successful migration is a marathon, not a sprint. It requires a thoughtful, phased approach.</p>
<h3 id="heading-phase-1-the-pilot-project-weeks-1-4">Phase 1: The Pilot Project (Weeks 1-4)</h3>
<p>Dont start by converting your most critical service. Choose a small, non-critical component or a new greenfield project. The goal is to learn, not to deliver a business-critical feature.</p>
<ul>
<li><p><strong>Team:</strong> Assign 2-3 enthusiastic engineers.</p>
</li>
<li><p><strong>Goals:</strong></p>
<ul>
<li><p>Validate Kotlins benefits on your specific codebase.</p>
</li>
<li><p>Get a feel for the learning curve.</p>
</li>
<li><p>Assess the impact on build times.</p>
</li>
</ul>
</li>
<li><p><strong>Outcome:</strong> A go/no-go decision backed by data, not just enthusiasm.</p>
</li>
</ul>
<h3 id="heading-phase-2-building-the-foundation-months-1-2">Phase 2: Building the Foundation (Months 1-2)</h3>
<p>Once youve committed, lay the groundwork for a broader rollout.</p>
<ul>
<li><p><strong>Establish Coding Standards:</strong> How will you handle nullability? Whats your policy on extension functions? Document these decisions.</p>
</li>
<li><p><strong>Configure Your Build:</strong> Enable incremental compilation. Set up static analysis tools like <code>ktlint</code>.</p>
</li>
<li><p><strong>Create a Kotlin Champions Team:</strong> This small group becomes the go-to resource for other developers.</p>
</li>
</ul>
<h3 id="heading-phase-3-gradual-adoption-months-2-12">Phase 3: Gradual Adoption (Months 2-12)</h3>
<p>Now, the real work begins. Start converting your codebase, but do it strategically.</p>
<ul>
<li><p><strong>Start with Tests:</strong> Unit and integration tests are the safest place to start. They have few dependencies and provide immediate feedback.</p>
</li>
<li><p><strong>Convert Data Models:</strong> POJOs/DTOs are easy wins thanks to data classes.</p>
</li>
<li><p><strong>Move to Service/Logic Layers:</strong> Once your models are in Kotlin, move up the stack to the business logic.</p>
</li>
<li><p><strong>Leave Controllers/Framework Code for Last:</strong> Code that heavily interacts with Java frameworks can be trickier to convert idiomatically. Save it for when the team is more experienced.</p>
</li>
</ul>
<p>Use the <strong>automated J2K converter</strong> built into IntelliJ IDEA, but treat its output as a starting point. Always have a human review the converted code to make it more idiomatic.</p>
<h3 id="heading-phase-4-maturity-12-months">Phase 4: Maturity (12+ Months)</h3>
<p>At this stage, Kotlin is no longer a novelty. Its a standard part of your stack.</p>
<ul>
<li><p>Most new code is written in Kotlin by default.</p>
</li>
<li><p>The team is comfortable and productive.</p>
</li>
<li><p>Legacy Java code is refactored to Kotlin as its touched.</p>
</li>
</ul>
<hr />
<h2 id="heading-perspectives-what-it-means-for-you">Perspectives: What It Means for You</h2>
<h3 id="heading-for-the-junior-developer">For the Junior Developer</h3>
<p>Learning Kotlin is a fantastic career investment. It exposes you to modern language features like functional programming and structured concurrency. Dont be intimidated. Leverage your Java knowledgethe underlying concepts of the JVM are the same. Focus on mastering null safety and data classes first. Pair program with a senior dev and dont be afraid to ask questions.</p>
<h3 id="heading-for-the-senior-developer-amp-architect">For the Senior Developer &amp; Architect</h3>
<p>Your role is strategic. You need to look beyond the syntax and consider the architectural implications. How can sealed classes improve your domain modeling? How can coroutines simplify your concurrency patterns? Your job is to guide the team, manage the risks (like build time increases), and ensure the migration delivers on its promise of higher quality and productivity.</p>
<h2 id="heading-conclusion-an-evolution-not-a-revolution">Conclusion: An Evolution, Not a Revolution</h2>
<p>Switching from Java to Kotlin is not about abandoning a trusted tool. Its about embracing a modern, more powerful one that was built to solve the very problems weve been wrestling with in Java for years. Thanks to its seamless interoperability, pragmatic feature set, and proven success at scale, Kotlin offers a low-risk, high-reward path to modernizing your server-side development.</p>
<p>Its an evolution, and its one your team is ready to make.</p>
<hr />
<h3 id="heading-references">References</h3>
<ol>
<li><p><strong>Kotlin Documentation:</strong> <a target="_blank" href="http://kotlinlang.org">kotlinlang.org</a></p>
</li>
<li><p><strong>Spring Boot and Kotlin Tutorial:</strong> <a target="_blank" href="http://spring.io/guides/tutorials/spring-boot-kotlin">spring.io/guides/tutorials/spring-boot-kotlin</a></p>
</li>
<li><p><strong>Meta Engineering Blog on Kotlin Migration:</strong> <a target="_blank" href="http://engineering.fb.com">engineering.fb.com</a></p>
</li>
<li><p><strong>Why did developers migrate Android applications from Java to Kotlin? (ArXiv):</strong> <a target="_blank" href="http://arxiv.org/abs/2003.12730">arxiv.org/abs/2003.12730</a></p>
</li>
</ol>
]]></description><link>https://daisuke.masuda.tokyo/article-2025-12-29-1014</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2025-12-29-1014</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Java]]></category><category><![CDATA[server side]]></category><category><![CDATA[backend]]></category><category><![CDATA[migration]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item><item><title><![CDATA[Beyond the Keyboard: How I 4x-ed My Developer Productivity with Voice]]></title><description><![CDATA[<p>Every developer knows the feeling. You have a brilliant, elegant solution in your mind, but a frustrating gap exists between that idea and the code materializing in your editor. Its a gap filled with boilerplate, syntax juggling, context switching, and the simple, physical limitation of your fingers on a keyboard.</p>
<p>For decades, weve accepted this friction as a fundamental part of the job. But what if it wasnt? What if you could close that gap and operate at the speed of thought? This isnt science fiction. For the past month, Ive been living this reality by shifting my primary development interface from my keyboard to my voice, all thanks to a tool called <a target="_blank" href="https://wisprflow.ai/"><strong>Wispr Flow</strong></a>.</p>
<p>This shift is part of a larger movement in software development, a new paradigm perfectly encapsulated by OpenAIs Andrej Karpathy in a now-famous tweet:</p>
<blockquote>
<p><a target="_blank" href="https://x.com/karpathy/status/1617979122625712128?lang=en">"The hottest new programming language is English."</a></p>
</blockquote>
<p>This is the essence of "Vibe Coding": focusing on the <em>what</em> and letting an AI assistant handle the <em>how</em>. And Ive found that voice is the ultimate, high-bandwidth interface for it.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://speakerdeck.com/x5gtrn/wispr-flow-the-voice-os-for-engineers">https://speakerdeck.com/x5gtrn/wispr-flow-the-voice-os-for-engineers</a></div>
<p> </p>
<h2 id="heading-the-keyboard-bottleneck-more-than-just-speed">The Keyboard Bottleneck: More Than Just Speed</h2>
<p>Let's start with the raw numbers. The average person types at around 40-45 words per minute (WPM). In contrast, the average person speaks at 150-220 WPM. Wispr Flow clocks my voice input at a consistent 220 WPM. Thats not just an incremental improvement; its a 4x leap in raw output speed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766834501134/28d678fd-6c50-4b1a-a884-a55e9cc8de8a.jpeg" alt class="image--center mx-auto" /></p>
<p>But the real bottleneck isnt just speed. Its the cognitive and physical toll. The mental energy spent correcting typos, remembering complex syntax, or navigating between files is energy <em>not</em> spent on solving the actual problem. Furthermore, the physical strain of typing for 8+ hours a day is a serious concern for long-term career sustainability. Repetitive Strain Injury (RSI) is a real threat that voice-driven development directly addresses.</p>
<h2 id="heading-wispr-flow-the-os-for-your-voice">Wispr Flow: The OS for Your Voice</h2>
<p>What makes Wispr Flow so effective is that its not another application you have to switch to. Its a non-invasive, intelligent overlay that works inside every app on your systemVS Code, iTerm, GitHub, Slack, Notion, you name it. It becomes a universal input method.</p>
<p>Here are the features that have made it indispensable to my workflow:</p>
<ul>
<li><p><strong>AI Auto-Edits:</strong> You speak naturally, including filler words and pauses. Flow cleans it up instantly.</p>
<ul>
<li><p><strong>I say:</strong> "Umm, so for the function, I think it should, like, take the <code>userId</code> and then, uh, return the profile."</p>
</li>
<li><p><strong>It types:</strong> "For the function, I think it should take the <code>userId</code> and then return the profile."</p>
</li>
</ul>
</li>
<li><p><strong>Context-Aware Dictionary:</strong> The tool quickly learns project-specific jargon, library names, and coding conventions. I no longer have to manually correct <code>Supabase</code> or spell out <code>Kubernetes</code>. It understands <code>camelCase</code>, <code>snake_case</code>, and acronyms from day one.</p>
</li>
<li><p><strong>Snippet Library:</strong> This is a game-changer for repetitive tasks. Ive set up a voice shortcut, <code>create bug report</code>, which instantly expands into a full Markdown template for filing a bug in Jira, complete with sections for reproduction steps, expected behavior, and actual behavior.</p>
</li>
</ul>
<h2 id="heading-vibe-coding-the-workflow-of-the-future">"Vibe Coding": The Workflow of the Future</h2>
<p>Vibe Coding is about elevating your role from a syntax-writer to an architectural director. You focus on the high-level logic and intent (the "vibe"), while offloading the mechanical implementation to an AI partner like GitHub Copilot or Cursor. The problem has always been the interface to these AIs. Typing prompts feels slow and clunky. Voice is the missing link.</p>
<p>Wispr Flow acts as the natural, high-bandwidth bridge to these tools. The workflow becomes a seamless loop: Think -&gt; Speak -&gt; AI Executes -&gt; Code Output.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766834541226/b5d7414c-5000-424c-8c65-ebf5f307d1e8.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-my-new-daily-workflows-in-action">My New Daily Workflows in Action</h2>
<p>This is where theory meets practice. Here are three concrete examples of how my daily tasks have been transformed.</p>
<h3 id="heading-1-ai-powered-scaffolding">1. AI-Powered Scaffolding</h3>
<p>Instead of manually typing out boilerplate for a new feature, I now describe it to Cursor via Wispr Flow.</p>
<p><strong>Scenario:</strong> Starting a new Express.js route.</p>
<p><strong>Voice Command:</strong> "Create a new Express router. Add a GET route for <code>/users/:id</code> that validates the ID is a number, fetches the user from a mock database, and returns the user object or a 404 error."</p>
<p><strong>Result:</strong> Within seconds, I have a fully formed, functional code block ready to be tested and integrated.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> router = express.Router();

<span class="hljs-comment">// Mock database</span>
<span class="hljs-keyword">const</span> users = [
  { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Alice'</span> },
  { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Bob'</span> },
];

router.get(<span class="hljs-string">'/users/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> id = <span class="hljs-built_in">parseInt</span>(req.params.id, <span class="hljs-number">10</span>);

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(id)) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).send({ <span class="hljs-attr">error</span>: <span class="hljs-string">'Invalid ID format'</span> });
  }

  <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.id === id);

  <span class="hljs-keyword">if</span> (!user) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">404</span>).send({ <span class="hljs-attr">error</span>: <span class="hljs-string">'User not found'</span> });
  }

  res.json(user);
});

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<h3 id="heading-2-hands-free-git">2. Hands-Free Git</h3>
<p>Committing code, especially writing descriptive messages, is now a fluid process.</p>
<p><strong>Scenario:</strong> Committing a new feature.</p>
<p><strong>Voice Command:</strong> "git commit with message feature: implement user profile endpoint with validation."</p>
<p><strong>Result:</strong> The command is executed in my terminal. This encourages me to write longer, more descriptive commit messages because its effortless.</p>
<pre><code class="lang-bash">$ git commit -m <span class="hljs-string">"feat: implement user profile endpoint with validation"</span>
</code></pre>
<h3 id="heading-3-documentation-in-seconds">3. Documentation in Seconds</h3>
<p>Writing PR descriptions, comments, and documentation used to be a chore. Now, its a quick debrief.</p>
<p><strong>Scenario:</strong> Writing a pull request description on GitHub.</p>
<p><strong>Voice Command:</strong> "In this PR, I have refactored the authentication service to use JWTs instead of session cookies. This improves statelessness and scalability for our microservices architecture. The key changes are in <code>authService.js</code> and <code>userController.js</code>. Please pay close attention to the new token validation middleware."</p>
<p>This level of detail, which might have been skipped before, is now standard because it takes only a few seconds to dictate.</p>
<h2 id="heading-beyond-code-the-holistic-benefits">Beyond Code: The Holistic Benefits</h2>
<p>The impact of this workflow extends beyond pure coding speed.</p>
<p>Its about <strong>sustainability</strong>. As Wispr Flows website highlights with a testimonial from a user with Parkinson's, this technology is a profound accessibility tool. For all developers, its a way to mitigate the risk of RSI and build a healthier, more sustainable career.</p>
<p>Its also about <strong>deep work</strong>. By removing the friction of the keyboard and context-switching to handle a quick Slack message or Jira update with my voice, I can stay in a state of flow for longer, more productive periods.</p>
<h2 id="heading-the-future-is-spoken">The Future is Spoken</h2>
<p>After a month of voice-driven development, going back to typing full-time feels archaic. Voice is not a gimmick; its the next logical evolution in how we interact with our development environments, especially as AI becomes a more integral co-pilot in our work.</p>
<p>By combining the creative, architectural thinking that humans excel at with the rapid, precise execution of AI, all connected by the natural interface of voice, were not just coding faster. Were changing the very nature of how we build software.</p>
<p>If you're a developer looking to break through the productivity plateau, I highly encourage you to give this a try. Your hands will thank you, and your brain will be free to focus on what truly matters: building great things.</p>
<p><strong>Ready to try it?</strong> <a target="_blank" href="https://wisprflow.ai/"><strong>Download Wispr Flow for free</strong></a> <strong>and experience it for yourself.</strong></p>
<hr />
<h3 id="heading-references">References</h3>
<p>Wispr Flow. <em>Flow for Developers</em>. <a target="_blank" href="https://wisprflow.ai/developers">https://wisprflow.ai/developers</a>.</p>
]]></description><link>https://daisuke.masuda.tokyo/article-2025-12-26-2025</link><guid isPermaLink="true">https://daisuke.masuda.tokyo/article-2025-12-26-2025</guid><category><![CDATA[Productivity]]></category><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[AI]]></category><category><![CDATA[vibe coding]]></category><category><![CDATA[#VoiceAI]]></category><category><![CDATA[writing]]></category><dc:creator><![CDATA[Daisuke Masuda]]></dc:creator></item></channel></rss>