[{"content":"Client — logistics technology provider, South Africa\nRole — Solution architect and pre-sales lead\nStatus — CEO-level proposal with live demo\nThe problem # Inbound support volume was growing faster than the client could hire. Call handling was human-staffed, agent turnover was high, and after-hours coverage did not exist. The client wanted \u0026ldquo;an AI that answers the phone\u0026rdquo; — which, as usual, was a symptom description rather than a requirement.\nDiscovery narrowed it down to three things that actually mattered: response latency low enough to feel like conversation, answers grounded in the client\u0026rsquo;s own operational data rather than model priors, and a clean escalation path to a human without the caller repeating themselves.\nArchitecture # Layer Choice Rationale Telephony SIP trunk into a real-time media server Keeps carrier integration decoupled from agent logic Real-time orchestration LiveKit agents Barge-in and interruption handling out of the box Speech to text Streaming ASR with domain vocabulary boosting Product SKUs and place names are where generic ASR fails Reasoning LLM with tool calling Tools for order lookup, booking status, escalation Knowledge grounding RAG over client SOPs and product data Prevents confident fabrication on policy questions Text to speech Streaming neural TTS First-audio-byte latency is the perceptual bottleneck Handoff Warm transfer with conversation summary The caller does not start over The design constraint that drove everything was a sub-1.5 second voice-to-voice latency budget, allocated explicitly across each hop. Anything slower reads as a bad line and callers start talking over the agent.\nWhat I owned # End-to-end architecture and latency budget allocation Build-vs-buy analysis across managed voice-agent platforms versus a composed stack Commercial model — per-minute unit economics against fully-loaded human agent cost, including the honest version where AI containment rates fall short of vendor claims Live demo delivered in a CEO-level meeting Risk register: ASR accuracy on accented English, hallucination exposure on policy questions, carrier-side failure modes What I would flag to any client considering this # Containment rate is the whole business case, and it is the number vendors are most optimistic about. A pilot scoped to the top five intents will tell you more in three weeks than any RFP response will.\n","date":"20 July 2026","externalUrl":null,"permalink":"/projects/ai-voice-agent-call-center/","section":"Projects","summary":"Replacing a human-staffed inbound call centre with a low-latency voice agent stack — LiveKit, Deepgram, RAG grounding and live telephony handoff.","title":"AI Voice Agent Call Centre Platform","type":"projects"},{"content":"Client — global electronics manufacturing services provider\nRole — Solution strategy, PRD authoring, prototype design\nStatus — PRD and interactive prototypes delivered · phased build proposed, not commissioned\nThe problem # The client\u0026rsquo;s warehouse operations were running on tribal knowledge and spreadsheets. Throughput bottlenecks were visible in the KPI reports but nobody could attribute them — was it bin placement, picker routing, shift coverage, or upstream sequencing? Without attribution, every improvement proposal was a guess.\nApproach # Rather than pitching one monolithic system, I decomposed the opportunity into four independently valuable modules, each with its own baseline metric and payback case:\nJIT sequencing — align inbound material release with line consumption Bin optimisation — slotting by velocity, affinity and ergonomics Labour planning — shift coverage modelled against forecast demand Trolley routing — pick path optimisation within physical aisle constraints This structure mattered commercially as much as technically. It gave the client a way to start small, prove one module, and expand — instead of a single procurement decision they would defer for two quarters.\nDeliverables # Full product requirements document covering all four modules, data dependencies and integration surface (WMS, MES, ERP) Interactive React prototypes for each module — clickable enough that stakeholders argued about the right things instead of the colour scheme Phased roadmap with per-module baseline metrics and expected payback Data readiness assessment: which modules were blocked on data the client did not yet capture The honest finding # Two of the four modules were not buildable at the accuracy the client wanted, because the underlying movement data was not being captured at sufficient granularity. That went into the proposal explicitly, with instrumentation as a prerequisite phase. Surfacing that early cost us scope in round one and bought credibility that carried the rest of the engagement.\n","date":"15 June 2026","externalUrl":null,"permalink":"/projects/warehouse-optimization-platform/","section":"Projects","summary":"A four-module optimisation platform for a global electronics manufacturer — JIT sequencing, bin allocation, labour planning and trolley routing, with an interactive prototype used to close the strategy phase.","title":"Warehouse Optimisation Platform","type":"projects"},{"content":"Client — third-party administrator, Malaysian health insurance\nRole — Architect and hands-on builder\nStatus — Working POC delivered against the client\u0026rsquo;s historical claim sample\nThe problem # Claims adjudication was manual, slow and inconsistent between assessors. The client came in asking for an AI solution — the assumption being that an LLM would read policy documents and decide claims.\nWhy I argued against AI # Adjudication logic in this domain is not ambiguous. Benefit limits, co-payment tiers, pro-ration rules, waiting periods, exclusions — these are written down, deterministic, and auditable by regulation. An LLM would introduce non-determinism into a process that legally requires reproducibility, and would make every denied claim harder to defend, not easier.\nThe actual bottleneck was that the rules lived across dozens of policy documents and nobody had encoded them.\nWhat I built # A Python rules engine implementing the client\u0026rsquo;s benefit schedule as executable, testable logic:\nBenefit-limit evaluation with annual and per-incident caps Co-payment and deductible tiers Pro-ration logic for mid-term policy changes — the hardest rule in the schedule, and the one assessors most often got wrong Waiting period and exclusion checks Full decision trace on every claim: which rule fired, in what order, against which limit The trace was the feature that sold it. Every adjudication decision could be explained line by line — something no LLM approach could offer at the time.\nOutcome # The POC processed the client\u0026rsquo;s historical claim sample and surfaced inconsistencies in past manual adjudications. AI stayed in the roadmap, but scoped to where it actually helps: document intake, OCR and structured extraction from unstructured medical bills — feeding the deterministic engine, not replacing it.\n","date":"10 May 2026","externalUrl":null,"permalink":"/projects/claims-adjudication-engine/","section":"Projects","summary":"A deterministic Python rules engine for Malaysian health insurance claims — built as a working POC to prove that the right answer was not an LLM.","title":"Claims Adjudication Rules Engine","type":"projects"},{"content":"Client — Ministry of Foreign Affairs, Vietnam (via CMC Global)\nRole — Lead business analyst and solution owner\nStatus — PRD, data model and architecture delivered\nContext # A national digital platform to support science and technology diplomacy — connecting institutions, knowledge resources and AI-assisted workflows across Vietnam\u0026rsquo;s diplomatic and research networks.\nThe constraint that shaped everything # Government procurement, data sovereignty requirements and long-term maintainability pointed to one conclusion: no proprietary SaaS in the core stack. Every component had to be self-hostable, auditable and replaceable without a vendor conversation.\nStack # Concern Choice Identity and access Keycloak — SSO, role hierarchy, federation-ready Data platform Supabase (self-hosted PostgreSQL) — row-level security aligned to organisational roles Workflow automation n8n — visual workflows that non-engineers on the ministry side can audit Visualisation globe.gl for network and relationship mapping What I owned # Requirements elicitation across ministry stakeholders with varying technical fluency Full PRD, data model and role/permission matrix Architecture decisions and open-source component evaluation Workflow design for approval chains and multi-tier review Reflection # The interesting engineering problem was not any single component — it was permission modelling. Diplomatic workflows have approval chains that do not map cleanly onto standard RBAC, and getting row-level security to express them without a hand-rolled authorisation layer took several iterations.\n","date":"1 February 2026","externalUrl":null,"permalink":"/projects/std-platform-mofa/","section":"Projects","summary":"A national platform for Vietnam’s Ministry of Foreign Affairs, built entirely on open-source infrastructure — Keycloak, Supabase, n8n.","title":"Science \u0026 Technology Diplomacy Platform","type":"projects"},{"content":"Clients — physical security and enterprise operations, APAC\nRole — Solution architect and pitch lead\nStatus — Architecture and pitch delivered across several pursuits · POCs for video analytics and OCR\nThe scaling problem # Facial recognition demos work beautifully with four cameras. At 200+ cameras the architecture that got you the demo collapses — bandwidth, inference cost and latency all break at roughly the same point.\nThe design answer was to stop shipping video to the model and start shipping the model to the video.\nArchitecture # Edge inference nodes — detection and embedding extraction on NVIDIA Jetson class hardware, one node per camera cluster Embeddings, not frames — only vectors and metadata cross the network, cutting upstream bandwidth by orders of magnitude Central matching service — vector search against the enrolled identity database Offline-first operation — nodes continue detecting and buffer results through network partitions OTA model deployment — model updates rolled out per-cluster with staged rollback Related engagements extended the same pattern to video analytics and OCR — container and vehicle identification for a customs tracking proposal, and document extraction pipelines using detection plus OCR at the edge.\nCommercial dimension # I also owned the licensing model — per-camera AI ID licensing versus per-node versus flat site licence — and built the pitch deck and presentation scripts used in client-facing delivery. On-premise deployment was non-negotiable for most prospects in this space, which ruled out several cloud-native vendors and shaped the competitive positioning.\n","date":"15 January 2026","externalUrl":null,"permalink":"/projects/edge-computer-vision/","section":"Projects","summary":"Architecture for edge-based facial recognition scaling to 200+ cameras, plus video analytics and OCR POCs delivered across APAC clients.","title":"Edge Facial Recognition \u0026 Video Analytics","type":"projects"},{"content":"Status — Shipped and live on both stores\nPlatforms — iOS — App Store · Android — Google Play\nStack — Flutter, Dart, XenForo API, Firebase Cloud Messaging\nSite — thenextvoz.htknguyen.dev\nWhy # VOZ is Vietnam\u0026rsquo;s largest tech forum and it had no decent mobile experience. Reading it on a phone meant a browser, pinch-zoom and a lot of regret. So I built the client I wanted.\nWhat it does # Mobile-optimised reading with full BBCode rendering, code highlighting and inline media Post, reply, react, quote, spoiler tags, image attachments Private messaging Push notifications for quotes, reactions and mentions Advanced search — by thread, user and date range Bookmarks, dark mode, adjustable typography, Vietnamese and English UI Pro tier: multi-account switching, compact mode, draft saving, RSS feed Engineering notes # The genuinely hard parts were not the UI:\nXenForo integration — session and CSRF handling against a forum with no official public API, staying strictly within the forum\u0026rsquo;s stated rules on request patterns Push notification bridge — building a VAPID/Web Push to FCM bridge so forum events could reach native devices BBCode rendering — a full parser and Flutter widget tree, because the forum\u0026rsquo;s dialect includes custom tags no off-the-shelf package handles Rate discipline — one user tap equals one server request, no prefetching or page-merging, per the forum\u0026rsquo;s explicit rules for third-party clients Constraint I chose to respect # The forum administrators published rules for third-party app developers: no server abuse, no advertising, mandatory disclosure that the app is unofficial, and a required support thread. I followed all of them, negotiated directly with the admins on features that touched request volume, and built the monetisation model around a paid tier rather than ads. Shipping something that survives contact with the community it serves matters more than shipping fast.\n","date":"20 March 2026","externalUrl":null,"permalink":"/projects/thenextvoz/","section":"Projects","summary":"A third-party mobile client for Vietnam’s largest tech forum — live on the App Store and Google Play, built solo.","title":"theNextVoz — Flutter Forum Client","type":"projects"},{"content":"Status — In development · not yet released\nStack — Flutter, Firebase, Gemini, pgvector\nThe problem # Vietnamese news has a duplication problem. One press release becomes forty near-identical articles across forty outlets within an hour. Any RSS reader that shows you all forty is worse than useless.\nApproach # Aggregate across Vietnamese news sources via RSS Embed each article and cluster by semantic similarity — same story, multiple outlets, one entry AI-generated summaries per cluster, with the source list preserved so you can see who covered it and how differently Auto-tagging for topic filtering What was harder than expected # Clustering thresholds. Too tight and you get duplicate clusters for the same story; too loose and two unrelated stories about the same ministry collapse into one. There is no single correct threshold — it varies by topic density and time window. The working solution used time-windowed clustering with topic-adaptive thresholds.\nVietnamese embedding quality. Off-the-shelf multilingual embedding models handle Vietnamese unevenly, especially for named entities and compound terms. Evaluating that properly meant building a labelled test set by hand.\n","date":"5 April 2026","externalUrl":null,"permalink":"/projects/tingon/","section":"Projects","summary":"RSS aggregation with AI-driven clustering and de-duplication for Vietnamese news. Flutter, Firebase, Gemini, pgvector.","title":"TinGon — AI Vietnamese News Reader","type":"projects"},{"content":"Status — Engine built and rendering · channel not launched\nStack — Remotion, ElevenLabs TTS, sprite-based animation engine\nThe idea # A Vietnamese storytelling and audiobook channel — but produced programmatically rather than hand-animated, so the marginal cost of the next episode approaches zero.\nThe engine # I designed a sprite-based video engine around three ideas:\nECP model — entity, component, property separation so scenes are described as data rather than hand-placed elements AnchorResolver pattern — sprite positioning resolved against named anchors, so a scene layout survives asset changes Remotion rendering — React components as video frames, with the whole composition driven by a script file plus a timed narration track Narration is TTS-generated, timed against the script, and drives sprite state transitions automatically.\nThe honest assessment # Remotion solves the rendering bottleneck completely. But rendering was never the bottleneck — writing was. A channel like this is constrained by how fast you can produce good scripts, and no amount of pipeline automation moves that number. The engine was worth building; it just did not unlock what I expected it to.\nThe same infrastructure is far better matched to data-driven content, where the input is a feed rather than a person\u0026rsquo;s imagination. Roughly 80% of the codebase transfers directly to that use case.\n","date":"29 June 2026","externalUrl":null,"permalink":"/projects/muc-va-dem/","section":"Projects","summary":"A Vietnamese audiobook and storytelling YouTube channel with a programmatic video engine — sprite-based animation, TTS narration, Remotion rendering.","title":"Muc \u0026 Dem — Automated Storytelling Video Pipeline","type":"projects"},{"content":"Status — Personal system, run privately · not a product and not offered to anyone\nStack — Node.js, Binance Futures API, XGBoost, LSTM\nWhat it is # A swing trading system running an ensemble of strategies rather than a single edge:\nTrend following, mean reversion and breakout strategies running concurrently Macro regime detection — the ensemble weights each strategy by detected market regime, because a mean-reversion strategy in a trending regime is a reliable way to lose money slowly ML-based signal scoring to filter low-conviction entries Full backtesting harness with walk-forward validation What I actually learned # Most of the engineering effort went somewhere unglamorous: avoiding lookahead bias in the backtester. It is trivially easy to write a backtest that produces a beautiful equity curve because it quietly uses information that would not have been available at decision time. Every version of that bug looks like a discovery until you fix it.\nThe second lesson: position sizing and risk limits contribute more to outcomes than signal quality does. A mediocre signal with disciplined sizing outperforms a good signal without it.\nBuilt for my own use — not investment advice, and not offered as a product.\n","date":"10 January 2026","externalUrl":null,"permalink":"/projects/trading-bot/","section":"Projects","summary":"A Node.js futures trading bot built for my own use — multi-strategy ensemble with macro regime detection, backtesting and ML-based signal scoring.","title":"Multi-Strategy Algorithmic Trading System","type":"projects"},{"content":"","date":"20 August 2026","externalUrl":null,"permalink":"/tags/ai/","section":"Tags","summary":"","title":"AI","type":"tags"},{"content":"","date":"20 August 2026","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"There is a row in one of my old estimates that reads \u0026ldquo;Prompt engineering \u0026amp; tuning — 15 MD.\u0026rdquo; Every word of it is fiction except the ampersand.\nNot because the number was too low, although it was. It is fiction because it is formatted to look like the rows around it — \u0026ldquo;API integration — 12 MD\u0026rdquo;, \u0026ldquo;Admin screens — 18 MD\u0026rdquo; — as if it were the same kind of quantity. It is not. Those rows are tasks. This row is a loop wearing a task\u0026rsquo;s clothes.\nMy About page says estimates are built bottom-up: WBS, effort, buffer, margin, not a number reverse-engineered from what the client hoped to hear. I stand by that. But bottom-up estimation carries an assumption so old nobody states it anymore: that the work can be enumerated. AI scope breaks that assumption, and most of the AI estimates I see — including my own early ones — deal with the breakage by pretending it did not happen.\nA WBS assumes \u0026ldquo;done\u0026rdquo; is observable # Classical estimation works because tasks terminate visibly. The screen renders or it does not. The endpoint returns the payload or it does not. The migration runs. Estimating is the act of decomposing scope until every piece is small enough that you have built something like it before, then summing.\nAI work breaks both halves of that. You often have not built something like it before — not because the architecture is novel, but because the data is. And \u0026ldquo;done\u0026rdquo; is not an event; it is a quality bar. Extraction is never finished. It reaches 91% on the sample you have, and someone has to decide whether the next point is worth two more weeks, and whether the sample even resembles production.\nThat is the structural difference: deterministic work is a line, AI work is a loop. A line has a length. A loop has an iteration count, and the iteration count is precisely the thing you do not know at proposal time. You can enumerate the tasks around the loop — ingestion, schema, deployment, the admin screens. You cannot enumerate the loop itself. Writing \u0026ldquo;15 MD\u0026rdquo; on it is not estimating; it is rounding your uncertainty to the nearest number that fits in a cell.\nWhere the budget actually goes # Three places, and none of them looks like a task in a WBS.\nData cleanup. Unknowable until the client\u0026rsquo;s data arrives, and the client\u0026rsquo;s data always arrives late and worse than described. In a warehouse optimisation engagement, two of the four modules the client wanted were not buildable at the accuracy they wanted, because the underlying movement data was not captured at sufficient granularity. There is no man-day figure that fixes absent data. What that scope needed was not effort but a prerequisite instrumentation phase — which is what we proposed, and which cost us size in round one and bought credibility for the rest of the engagement.\nThe measuring stick. Nobody budgets for building the thing that tells you whether the system works. On the voice agent platform, the entire business case rests on containment rate — the share of calls the agent resolves without a human. You cannot measure containment without knowing what your calls actually contain, which means labelled transcripts, an intent taxonomy, and agreed definitions of \u0026ldquo;resolved\u0026rdquo;. That is real work. It appears in almost no vendor estimate I have ever reviewed, mine included, and it is the work that determines whether every other number in the proposal means anything.\nThe plateau. The first 80% of quality arrives in the first week. That week becomes the demo, the demo becomes the client\u0026rsquo;s expectation, and the expectation becomes a number in Appendix B. The remaining points are the actual project, and they get harder non-linearly. In the satire I wrote about a \u0026ldquo;95% extraction accuracy\u0026rdquo; that made it from a Friday-night POC into a contract — it really did hit 95%, on the twelve images that were selected. That is fiction, but the mechanism is not: the plateau is where AI projects go to die, and it is invisible in any estimate built from tasks.\nEstimate the loop, not the task # The constructive move is to stop disguising the loop and price it as what it is. Instead of \u0026ldquo;Tuning — 20 MD\u0026rdquo;, the row becomes a structure:\nA quality gate. The metric, how it is measured, and on what data. \u0026ldquo;95% extraction accuracy\u0026rdquo; is not a gate; \u0026ldquo;≥95% field-level exact match on a 500-document held-out sample drawn from the client\u0026rsquo;s production archive\u0026rdquo; is. A cost per iteration. One cycle of error analysis, change, re-evaluation. This is estimable — it is ordinary engineering work with a visible end. An iteration cap. The number of cycles the price includes. Not a guess at how many you will need — a statement of how many the client has bought. Exit criteria, including the honest one. Gate reached: proceed. Cap reached, gate not reached: here is the number we did reach, here is the error analysis, here is the decision point. \u0026ldquo;The bar is not reachable with your current data\u0026rdquo; is a legitimate project outcome, and pricing it as one is the difference between a finding and a failure. What this produces is the price of an experiment with a capped downside, and I have found clients accept that far more readily than the industry assumes — provided it is presented as an experiment. What they do not accept is an experiment that was priced as a certainty, discovered to be an experiment in month four.\nAssumptions are the contract # In the satire, the pre-sales guy writes two assumptions on page 23 and feels much better. Nobody reads page 23. When the client\u0026rsquo;s API arrives in week six bearing no resemblance to its documentation, the PM declines to fight about it, and the assumption dies the quiet death it was always going to die.\nOn deterministic scope, the assumptions section is protective boilerplate — it exists so that when things go wrong, you can point at it. On AI scope it is load-bearing, because the assumptions are not edge conditions. They are the inputs to the loop. Three belong on the page every time:\nA data quality floor, stated measurably, against a sample actually received before signature. \u0026ldquo;Client provides clean data\u0026rdquo; is a wish. \u0026ldquo;Estimate assumes ≤8% of documents are handwritten, per the 200-document sample reviewed on \u0026rdquo; is an assumption. Accuracy as a range tied to a measurement method. A naked \u0026ldquo;95%\u0026rdquo; in a proposal will be read as a promise, quoted back at UAT, and there will be nothing to say. A range with a method is a claim you can defend line by line. Client-side expert hours. Labelling, reviewing evaluation output, adjudicating what the correct answer even is. This is the assumption clients break most often, because nobody told their operations team that \u0026ldquo;buying AI\u0026rdquo; meant lending it their best assessor two days a week. The test I apply: if this assumption breaking would kill the project, it is not an assumption — it is a phase gate. Move it out of page 23 and into the plan, as paid work whose deliverable is the assumption retired. That is what the instrumentation phase was in the warehouse proposal: an assumption too important to be one.\nThe conversation with sales # Then the number comes back too high. It always comes back too high; the competition is quoting three months, and we have AI now.\nThe move that loses is defending the total, because the total is built on uncertainty and sales can smell it. The move that works is restructuring: split the engagement at the point of maximum ignorance. A feasibility spike — small, fixed-price, a few weeks — that retires the named unknowns: it builds the measuring stick, runs the loop a handful of times on the client\u0026rsquo;s real data, and comes back with an actual number instead of a hoped one. Then a committed build, priced on what the spike found, by people who are no longer guessing.\nEveryone\u0026rsquo;s incentives survive contact with this. Sales gets a small number to sell now, this quarter. Delivery gets to price the build with data instead of bravado. The client gets a kill point that costs them weeks instead of quarters — which is a feature you can sell, not a hedge you have to hide. On the voice agent engagement I put it in the proposal in exactly those terms: a pilot scoped to the top five intents will tell you more in three weeks than any RFP response will.\nSometimes procurement insists anyway: one fixed number, whole scope, up front. That is not a formality. That is the client telling you which risks they have decided not to own. Price those risks like you are the one holding them — because you are — or decline the deal. Both are better than the third option, which is the satire, played out in real time, with your name on page 14.\nError bars, written down # An estimate is a model of the project. On deterministic work the model can be precise, and precision is a courtesy. On AI work the honest model has error bars, and the dishonest model has the same error bars — hidden, and discovered at UAT.\nClients do not punish error bars written down. They punish false precision, just later, at the acceptance meeting, at reference-check time, in the eighteen months you spend as the vendor who oversold. The margin an honest estimate protects never appears in the spreadsheet. It is the credibility that prices the second deal.\nSomewhere, on a Friday night, a pre-sales guy is trimming a buffer to make a number competitive. The row he should be looking at instead is the one that says \u0026ldquo;Prompt engineering \u0026amp; tuning — 15 MD\u0026rdquo;. One of those rows is padding. The other one is the project.\n","date":"20 August 2026","externalUrl":null,"permalink":"/posts/estimating-work-nobody-has-estimated-before/","section":"Writing","summary":"Bottom-up estimation assumes you can enumerate the tasks. AI projects break that assumption. How I price the loop instead of the line — and what belongs on page 23.","title":"Estimating Work Nobody Has Estimated Before","type":"posts"},{"content":"","date":"20 August 2026","externalUrl":null,"permalink":"/tags/estimation/","section":"Tags","summary":"","title":"Estimation","type":"tags"},{"content":"","date":"20 August 2026","externalUrl":null,"permalink":"/categories/industry/","section":"Categories","summary":"","title":"Industry","type":"categories"},{"content":"I design enterprise AI solutions and win the deals that fund them.\nBased in Da Nang, working across Singapore, Malaysia and the wider APAC region. My day job sits at the intersection most people treat as two separate jobs: solution architecture — what gets built, and whether it can actually be built — and pre-sales — what it costs, why the client should believe us, and how the deal closes.\nEnterprise AI architecture across RAG, voice agents, computer vision at the edge, and digital twin. Pre-sales engineering from RFP response and WBS-based costing through pricing strategy and technical proposal authoring. Discovery and solutioning workshops with C-suite, technical leads and procurement.\nSGD 1M pipeline closed · 100+ proposals and tenders authored · +15% win rate · 15+ enterprise architectures across semiconductor, aviation, BFSI, healthcare, logistics and facility management\nI still write code. A Flutter forum client live on both app stores, a futures trading bot I run on my own account, and a home lab that exists mainly so I have somewhere to break things. That hands-on layer is not nostalgia — it is why my estimates hold up in delivery.\nRead the full resume · See selected projects\n","date":"20 August 2026","externalUrl":null,"permalink":"/","section":"Nguyen Hoang","summary":"I design enterprise AI solutions and win the deals that fund them.\nBased in Da Nang, working across Singapore, Malaysia and the wider APAC region. My day job sits at the intersection most people treat as two separate jobs: solution architecture — what gets built, and whether it can actually be built — and pre-sales — what it costs, why the client should believe us, and how the deal closes.\n","title":"Nguyen Hoang","type":"page"},{"content":"","date":"20 August 2026","externalUrl":null,"permalink":"/tags/pre-sales/","section":"Tags","summary":"","title":"Pre-Sales","type":"tags"},{"content":"","date":"20 August 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"Occasional notes on enterprise AI architecture, pre-sales practice and side-project engineering.\n","date":"20 August 2026","externalUrl":null,"permalink":"/posts/","section":"Writing","summary":"Occasional notes on enterprise AI architecture, pre-sales practice and side-project engineering.\n","title":"Writing","type":"posts"},{"content":"","date":"6 August 2026","externalUrl":null,"permalink":"/tags/outsourcing/","section":"Tags","summary":"","title":"Outsourcing","type":"tags"},{"content":"","date":"6 August 2026","externalUrl":null,"permalink":"/tags/satire/","section":"Tags","summary":"","title":"Satire","type":"tags"},{"content":" Fiction. Characters, projects, and numbers are all made up. Written for laughs on a weekend, not aimed at anyone or any project. If it looks like your company — coincidence. Or maybe that\u0026rsquo;s just how this industry works everywhere. First, the Sales guy meets the client. Charms them, sells them the dream. Fifteen minutes into the conversation he\u0026rsquo;s nodding along: \u0026ldquo;We can absolutely do all of this. Let me bring in our Pre-sales guy to go deeper.\u0026rdquo;\nThe Pre-sales guy gets a four-line brief at 9 PM on a Friday: client wants an internal system with AI, presentation Monday, just put together a deck and a small demo.\n\u0026ldquo;Small demo\u0026rdquo; means the entire weekend. He vibe-codes a POC: upload an image, AI extracts the numbers, a dashboard with smooth animated charts, plus a chatbot that answers anything in two seconds. The data is twelve hardcoded rows. But it looks good. It runs. It even has a loading animation.\nMonday\u0026rsquo;s presentation. The client is impressed. Their VP turns around: \u0026ldquo;You guys move fast — three days for this?\u0026rdquo; Sales beams: \u0026ldquo;That\u0026rsquo;s AI for you, sir. Multiplies our productivity.\u0026rdquo;\nThe Pre-sales guy sits at the far end of the table. He almost says something. He doesn\u0026rsquo;t.\nThe client nods and asks for a detailed proposal with pricing.\nHe does the estimate first: 5 months, 6 people. Sales looks at the number and sighs. \u0026ldquo;Man, the competition is quoting three months. And we have AI now — go back and redo it, trim the buffer, we need to be competitive.\u0026rdquo; He cuts integration effort, cuts the UAT buffer, lands on 3.5 months. Sales rounds it down to 3.\nAt the bottom of the estimate he writes two assumptions: the client provides API access to their existing system within the first two weeks, and scope does not change after sign-off. Writing that down makes him feel much better.\nThen he pulls up the recording from the client meeting, dumps the transcript into a chat window, asks for an SRS, and staples the estimate onto it. Thirty minutes later: an 80-page proposal. Executive Summary. Business Context. Non-Functional Requirements broken into seven subsections. A RACI matrix. A 24-row Risk Register in which risk #18 reads \u0026ldquo;Risk of misunderstanding business requirements — Mitigation: increase communication with the client.\u0026rdquo; His two assumptions sit on page 23.\nNobody reads the whole thing. Sales reads the pricing section. The Pre-sales guy re-reads the six pages he actually wrote himself. The client prints it, spiral-binds it, and drops it on their director\u0026rsquo;s desk. The director picks it up, gauges the thickness with his thumb, and nods: \u0026ldquo;These guys are thorough.\u0026rdquo;\nMeanwhile HR starts hiring. Four devs this time instead of six, because somebody forwarded a LinkedIn post into the leadership group claiming one developer plus AI equals two and a half developers.\nClient signs. Pays 30% upfront. Sales takes his 5% cut of that 30% — good month. The Pre-sales guy gets a \u0026ldquo;nice work\u0026rdquo; and a new brief. Presentation Thursday.\nThe team lead and the senior dev sit down to break down requirements and size the work. The team lead does the math: with these requirements, assuming absolutely nothing changes, eight months.\nThe PM goes quiet for a moment. He knows eight months is right. But the contract says three, and his KPI this year is on-time delivery rate. So he says: \u0026ldquo;I hear you. But we\u0026rsquo;ve got Cursor Business now. Just start — deliver well and I\u0026rsquo;ll make sure you get project bonus.\u0026rdquo; He doesn\u0026rsquo;t fully believe what he just said either.\nThe team lead opens the proposal. He stops at page 14 and messages the Pre-sales guy: \u0026ldquo;Where did \u0026lsquo;95% AI extraction accuracy\u0026rsquo; come from?\u0026rdquo; The answer: \u0026ldquo;It really did hit that in the demo.\u0026rdquo; It really did — on the twelve images that were selected. The conversation ends there. Page 14 is already in the contract, Appendix B, Scope of Work.\nThe team lead assigns people, splits tasks, sets up the scrum ceremonies, and rallies the room: \u0026ldquo;Two and a half months, team. Half a month of buffer.\u0026rdquo;\nMonth one, the velocity is glorious. A junior pushes 3,000-line PRs daily. The burndown chart falls off a cliff. The PM screenshots it for the company group chat. The senior dev can\u0026rsquo;t review fast enough and starts approving on vibes. Test coverage hits 85% — all AI-generated tests, asserting the mocks rather than the business logic.\nAlso in month one: the client\u0026rsquo;s API doesn\u0026rsquo;t exist yet. Their IT team says it needs security approval. The team builds mocks and keeps going.\nAfter a month, one dev quits. HR hires a replacement, and the PM pulls a dev off another project to help.\nA month later they discover the AI misread a domain term in the SRS — the client uses a word that differs from the industry standard. The misreading has spread across 40 files, because every time a junior hit an error they pasted the whole stale context back into the chat. Meanwhile the client has seen some startup\u0026rsquo;s demo and wants a chatbot added, for modernity. The team lead pushes back. The client opens his laptop and replays the POC from three months earlier: \u0026ldquo;But you already have this?\u0026rdquo; Nobody can explain that \u0026ldquo;this\u0026rdquo; was forty lines of API calls and a hardcoded array of answers.\nWeek six, the client\u0026rsquo;s API arrives. The format bears no resemblance to the documentation they sent originally, and three required fields are missing. The entire data access layer, built against mocks, has to be rewritten. The team lead pulls up page 23. The PM reads it and says: \u0026ldquo;Just do it. Fighting about it now sours the relationship — we\u0026rsquo;ll bundle it into a change request at the end.\u0026rdquo; Nobody ever files it.\nAnother month in, the project has failed perfectly. Not from too little code — from too much. Two hundred thousand lines for a system that should have been forty thousand. Three architectural patterns coexisting because three people prompted three different ways. The team lead jumps in to code alongside the two juniors, because the senior dev is in the hospital with tuberculosis.\nThe team lead reads the juniors\u0026rsquo; code and doesn\u0026rsquo;t understand it. He asks the juniors. They don\u0026rsquo;t understand it either. All they know is: \u0026ldquo;I told it to fix it and it fixed it.\u0026rdquo;\nThe PM pulls two more devs off another project. They need three weeks to onboard — longer than it used to take — because there\u0026rsquo;s nobody to ask why is it done this way here. Nobody knows. The author was a model, and its context window was cleared back in month two.\nMonth five, the client\u0026rsquo;s security team runs a scan on staging: API keys hardcoded in six places, a package in package.json that doesn\u0026rsquo;t exist on npm (the AI invented the name, and someone else has since registered it), and an admin endpoint with no role check because the AI assumed middleware handled it upstream.\nThen comes the scope meeting. Both sides pull out the 80-page document. The client points at page 31: the system synchronizes data in real time. The team lead flips to page 62: data synchronization runs in batches, four-hour default interval. Both sentences are in the contract. Both were written by the same model, thirty pages and roughly four minutes apart, and nobody had ever read those two pages in the same sitting.\nThe Pre-sales guy is summoned to the meeting in the role of technical credibility, meaning he sits there saying things like \u0026ldquo;we need to re-align on the architecture to ensure long-term scalability,\u0026rdquo; trying to make a three-month delay sound like a strategic decision. Then he flies out to pitch another client, with a deck containing a slide titled Proven Delivery Track Record, illustrated with a screenshot of the old POC.\nBy month six, the Sales guy has moved to another company. New title: AI Solutions Consultant. The PM is still negotiating extensions with the client. The senior dev is out of the hospital and has been back on overtime for a week. Everyone else is still coding and debugging. The team lead takes the occasional half-day off for interviews somewhere.\nBy month seven, there\u0026rsquo;s a demo the client can look at. UAT is scheduled for two weeks — precisely the number the Pre-sales guy cut from the estimate.\nUAT runs five weeks. The client logs 340 bugs. The team fixes 180, closes 60 as \u0026ldquo;as designed,\u0026rdquo; and pushes the remaining 100 to phase two — a phase that does not exist.\nBy month eight, the client signs a conditional acceptance and pays 40% of the project cost to receive a pile of source code that \u0026ldquo;works if you click the buttons in the documented order,\u0026rdquo; along with a declaration that they will never work with this vendor again — and a line that stings more: \u0026ldquo;I could have gotten this far sitting with an AI myself.\u0026rdquo; The Pre-sales guy hears about it secondhand from the PM. He understands the client\u0026rsquo;s feeling with total precision, because that is exactly what he did over a weekend in January.\nThe final 30% is tied to a warranty acceptance clause after three months in production. The client never signs it. The company never chases it either, because chasing it would mean reopening the 80-page document.\nBy month nine, the two junior devs are let go for insufficient skills and poor productivity. In reality, the company has discovered that a junior plus AI is still a junior, just faster. Leadership decides to cut fresher hiring next year. Nobody asks where the seniors will come from in five years.\nAt quarter close, the PM gets his project bonus as usual, because his on-time delivery rate is measured against the final extended deadline — which he proposed. The team lead has left to start his own company selling AI Transformation services to SMEs. The senior dev is somewhere else at double the salary, with a job description that reads code review and AI output validation. HR keeps hiring devs to fill the gaps.\nThe Pre-sales guy gets promoted. His win rate that quarter was 60%, the highest in the company. Nobody measures what happens after signature.\nThe company doesn\u0026rsquo;t go bankrupt. Next quarter it wins more deals, lands new clients, and somewhere a Pre-sales guy is vibe-coding a POC on a Friday night.\nOnly faster this time. AI, you know.\nReading this back, I was probably harsh on the Sales and PM crowd. In real life everyone is doing their best inside a measurement system that measures the wrong things. The Pre-sales guy included.\n","date":"6 August 2026","externalUrl":null,"permalink":"/posts/the-tragedy-of-a-software-outsourcing-company/","section":"Writing","summary":"A fictional nine-month project, from the Friday-night POC to the conditional acceptance nobody wanted. Everyone hits their KPI. Nobody measures what happens after signature.","title":"The Tragedy of a Software Outsourcing Company (2026 Edition)","type":"posts"},{"content":" The short version # I am a Solution Consultant at CMC Global, covering AI and enterprise pre-sales for APAC with Singapore and Malaysia as primary markets. I hold an MSc in Computer Science from Universiti Teknologi Malaysia, and I am AWS Certified AI Practitioner, PSM II and PSPO II certified.\nThe longer version # I started as a developer, moved into delivery leadership, and ended up in pre-sales — which turned out to be the role that uses all of it. A pre-sales architect who cannot code writes proposals that delivery teams quietly rewrite. A developer who cannot read a procurement gate builds elegant things nobody buys. The interesting work lives where those two constraints meet.\nMost of my engagements start the same way: a client describes a symptom, not a problem. Warehouse throughput is down. The call centre cannot scale. Claims adjudication takes three weeks. The first real deliverable is almost never architecture — it is a shared, honest definition of what is actually broken and what \u0026ldquo;solved\u0026rdquo; looks like in numbers.\nHow I work # Assumptions get written down. If an estimate depends on the client having a clean data feed, that goes on the page, not in my head. Risk gets flagged early, not managed later. A deal that dies at discovery costs less than one that dies in UAT. Stack-agnostic by default. The right answer is sometimes a deterministic rules engine, not an LLM. I have talked clients out of AI more than once. Estimates are built bottom-up. WBS, effort, buffer, margin — not a number reverse-engineered from what the client hoped to hear. Outside work # Card magic — sleight of hand, mostly close-up. Building and shipping side projects nobody asked for. A Proxmox home server running more services than it strictly needs.\nContact # Email — hoangtrankhoinguyen@gmail.com LinkedIn — linkedin.com/in/nguyen-hoang Location — Da Nang, Vietnam (ICT, UTC+7) ","date":"3 August 2026","externalUrl":null,"permalink":"/about/","section":"Nguyen Hoang","summary":"The short version # I am a Solution Consultant at CMC Global, covering AI and enterprise pre-sales for APAC with Singapore and Malaysia as primary markets. I hold an MSc in Computer Science from Universiti Teknologi Malaysia, and I am AWS Certified AI Practitioner, PSM II and PSPO II certified.\n","title":"About","type":"page"},{"content":"","date":"3 August 2026","externalUrl":null,"permalink":"/categories/architecture/","section":"Categories","summary":"","title":"Architecture","type":"categories"},{"content":"","date":"3 August 2026","externalUrl":null,"permalink":"/tags/architecture/","section":"Tags","summary":"","title":"Architecture","type":"tags"},{"content":"","date":"3 August 2026","externalUrl":null,"permalink":"/categories/engineering/","section":"Categories","summary":"","title":"Engineering","type":"categories"},{"content":"","date":"3 August 2026","externalUrl":null,"permalink":"/tags/flutter/","section":"Tags","summary":"","title":"Flutter","type":"tags"},{"content":"The most useful thing I do in a discovery workshop is occasionally talk the client out of the thing they came to buy.\nThis is not contrarianism. It is that the request arrives pre-shaped by the budget line it was approved against. Someone has an AI initiative to spend, so the problem gets described as an AI problem, and by the time it reaches a solution architect it has already been framed in a way that forecloses the better answer.\nThe request is downstream of the budget # A third-party administrator in Malaysian health insurance came to us wanting AI for claims adjudication. The framing was specific: an LLM would read the policy documents and decide the claims. Adjudication was manual, slow, and inconsistent between assessors — all true, all worth fixing.\nBut adjudication logic in that domain is not ambiguous. Benefit limits, co-payment tiers, pro-ration rules, waiting periods, exclusions — these are written down. They are deterministic. They are auditable by regulation. The inconsistency between assessors was not evidence that the rules were fuzzy; it was evidence that nobody had encoded them.\nThe bottleneck was never comprehension. It was that the rules lived across dozens of policy documents in the heads of people who had read them.\nNon-determinism is a liability, not a feature # In a regulated domain, every decision has to be defensible line by line. Someone denies a claim, the claimant disputes it, and the organisation has to reconstruct why — which rule fired, against which limit, in what order.\nAn LLM makes that harder in both directions. You get non-reproducibility on a process that legally requires reproducibility, and you get an explanation that is generated after the fact rather than being the actual mechanism of the decision. A plausible-sounding rationalisation is worse than no rationalisation, because it survives review.\nWhat we built instead was a Python rules engine implementing the benefit schedule as executable, testable logic. The feature that sold it was not accuracy — it was the decision trace. Every adjudication could be replayed rule by rule. Run against the client\u0026rsquo;s historical claim sample, it surfaced inconsistencies in past manual decisions, which is a thing you can only do when the logic is inspectable.\nWhere the AI actually went # AI stayed in the roadmap. It moved to where it earns its non-determinism: document intake, OCR, structured extraction from unstructured medical bills. Messy input, tolerant of error, cheap to verify, with a human or a schema check downstream.\nThat is the general shape. Deterministic core, AI at the edges. The model handles the part where the input is unstructured and the failure mode is \u0026ldquo;try again\u0026rdquo;. The engine handles the part where the output has to be defended in front of a regulator.\nIt is worth being precise about which side of that line a given step falls on. \u0026ldquo;Extract the diagnosis code from this bill\u0026rdquo; is an edge problem — verifiable against a code list. \u0026ldquo;Decide whether this diagnosis is covered under a policy in its waiting period\u0026rdquo; is a core problem. They look adjacent in a workflow diagram and they are not remotely the same risk.\nWhat the pattern looks like in discovery # The claims engagement was not unusual. The same shape recurs:\nThe client asks for AI because AI is what they have budget for. Discovery reveals the binding constraint is data capture, process inconsistency, or integration — none of which a model fixes. In a warehouse optimisation engagement, two of four proposed modules were not buildable at the accuracy the client wanted, because the underlying movement data was not being captured at sufficient granularity. No model architecture recovers information that was never recorded.\nSo the question I try to get answered before anything else: what is the actual constraint, and would a perfect model relax it? If a hypothetical oracle with perfect judgement still would not fix the problem, the problem is not a judgement problem.\nThe commercial part # The obvious objection is that this is a bad way to sell software. Telling a client their AI project should be a rules engine and a data instrumentation phase is a smaller first invoice than telling them yes.\nIt is a smaller invoice. It costs scope in round one. I have made that trade repeatedly and it has been correct every time, for a reason that has nothing to do with virtue: the alternative is a project that dies in UAT. A deal that gets right-sized at discovery costs everyone a fraction of what a deal that fails acceptance costs — in margin, in reference value, in the eighteen months you do not spend as the vendor who oversold.\nClients also notice. A vendor who says \u0026ldquo;not this part\u0026rdquo; is making a claim you can check, and the parts they do say yes to become more believable. Most of the pipeline I have closed came after a conversation where I argued against something.\nThe engineering version of the same principle: the right answer is sometimes a deterministic rules engine, and being the person who says so out loud is worth more than being the person who ships the demo.\n","date":"3 August 2026","externalUrl":null,"permalink":"/posts/why-not-every-problem-needs-an-llm/","section":"Writing","summary":"Notes on talking clients out of AI, and why deterministic logic still wins in regulated domains.","title":"Not Every Problem Needs an LLM","type":"posts"},{"content":"","date":"3 August 2026","externalUrl":null,"permalink":"/tags/productivity/","section":"Tags","summary":"","title":"Productivity","type":"tags"},{"content":"Nguyen Hoang — AI Solutions Architect \u0026amp; APAC Pre-Sales Consultant\nDa Nang, Vietnam · hoangtrankhoinguyen@gmail.com · LinkedIn · Download PDF\nSummary # AI Solutions Architect and Pre-Sales Consultant specialising in APAC enterprise pursuits — bridging deep technical architecture (digital twin, voice AI, RAG, computer vision, edge computing) with consultative business outcomes (ODC scaling, market entry, win-rate improvement). Closed SGD 1M pipeline across Singapore and Malaysia, authored 100+ proposals, and architected 15+ enterprise solutions spanning semiconductor manufacturing, travel and aviation, BFSI, healthcare, renewable energy and facility management. AWS Certified AI Practitioner with hands-on full-stack capability — proven by a published mobile app and production-grade systems — that gives every solutioning conversation engineering credibility.\nKey Achievements # Closed SGD 1M pipeline across APAC pre-sales engagements Authored 100+ proposals and tenders across Singapore, Malaysia and Vietnam Improved organisational win rate by 15% through standardised AI solutioning frameworks and a reusable proposal library Architected enterprise AI and cloud solutions across digital twin, voice AI, computer vision, RAG and edge computing — covering 6+ verticals Built an 80-account APAC ITO target list for the SG and MY markets, clustered by vertical, buying signal and entry angle Built FY2026 pipeline analytics covering 49 leads and USD 10M+ pipeline value, with concentration-risk and loss-pattern analysis Core Competencies # Pre-Sales \u0026amp; Solution Consulting # RFP/RFQ/SOW analysis · technical proposal authoring · WBS-based costing and effort modelling · pricing strategy (fixed-price vs T\u0026amp;M, buffer and margin design, tiered POC packaging) · client discovery workshops · requirement shaping · competitive intelligence · account-based research and GTM planning · pipeline analytics and win/loss forensics\nAI \u0026amp; Solution Architecture # Generative AI and RAG (pgvector, ChromaDB, embeddings, agentic orchestration) · voice AI (STT–LLM–TTS pipelines, sub-1.5s voice-to-voice latency budgets) · computer vision (detection, tracking, OCR, edge inference) · digital twin and discrete-event simulation · cloud-native and event-driven architecture · edge and IoT (offline-first sync, OTA deployment)\nDomain Depth # Semiconductor manufacturing (AMHS, OHT, MES, SECS/GEM, OPC-UA) · travel and aviation (GDS, NDC, BSP settlement, PNR) · BFSI (digital banking, payments, AML/KYC) · healthcare (FHIR, Medplum, claims adjudication) · logistics and warehousing · facility management · enterprise eCommerce (MACH, headless)\nBusiness \u0026amp; Delivery # ODC/GDC planning and governance · APAC market research and account targeting · vendor and partner ecosystem mapping · stakeholder communication across C-suite, technical leads and procurement · Agile/Scrum and hybrid delivery · UAT coordination and post-go-live stabilisation\nTechnical Summary # Category Details AI / GenAI Claude API, Gemini, OpenAI, RAG (pgvector, ChromaDB, Vectra), embeddings, agentic orchestration, prompt engineering, AWS Bedrock Voice AI LiveKit, Deepgram, ElevenLabs, Twilio SIP/Voice, ASR tuning for Vietnamese and Singlish Computer Vision YOLOv8, RT-DETR, PaddleOCR, DeepSORT/ByteTrack, ONNX Runtime, NVIDIA Jetson, Coral TPU Digital Twin / Simulation Three.js, Unreal Engine + Pixel Streaming, discrete-event simulation (AnyLogic, SimPy) Cloud / DevOps AWS (EC2, EKS, S3, RDS, Bedrock, Lambda), GCP (GKE, Cloud Functions, Firestore), Cloudflare, Docker, Kubernetes, K3s, Proxmox Backend Node.js, Python, NestJS, FastAPI, Laravel, Java Spring (solution level) Frontend / Mobile React, Next.js, Flutter/Dart, SwiftUI, Firebase, FCM/APNs, IAP, App Store \u0026amp; Play Console Data PostgreSQL, MySQL, MongoDB, TimescaleDB, Redis, Elasticsearch, vector databases Streaming / Messaging Kafka, MQTT, WebSocket, gRPC Architecture Patterns Microservices, event-driven, edge computing, serverless, headless commerce, MACH Tooling Jira, Confluence, Azure DevOps, Figma, Notion, Mermaid, draw.io, SQL, Excel modelling Experience # Solution Consultant — CMC Global # Da Nang, Vietnam · 07/2022 – Present\nLead AI and enterprise pre-sales for APAC clients (primary markets: Singapore and Malaysia), owning the full lifecycle from RFP analysis and discovery through technical solutioning, costing and proposal closure. Architect multi-domain enterprise solutions — voice AI call centres, computer vision surveillance, digital twin and simulation, RAG knowledge platforms, intelligent document processing — and defend those architectures in technical evaluation with client CTOs and procurement. Build bottom-up estimation models (WBS, effort, buffer, margin) and pricing strategies across fixed-price, T\u0026amp;M and tiered-POC commercial structures. Run discovery workshops and stakeholder mapping for enterprise pursuits; produce account research, org charts and entry-angle analysis for target accounts. Own resource augmentation pursuits end to end — role profiling, candidate assessment, interview question banks, rate card modelling and client submission. Maintain pipeline analytics and win/loss forensics used for regional GTM prioritisation. Backend Developer / Scrum Master — Digital Unicorn # 07/2021 – 07/2022\nJoined as a backend developer on Life In, a product built for the Belgian market, working on services and APIs alongside the product team. Moved into the Scrum Master role for the same team — running ceremonies, backlog refinement, estimation and release planning, and keeping delivery aligned between the engineering team and the product stakeholders in Belgium. Kept enough hands in the codebase to keep the process grounded: sprint scope negotiated against real technical constraints rather than optimism. Freelance Delivery Lead — Nadlo Webagentur (Remote) # 01/2018 – 06/2021\nRan a small freelance engineering team as the single client-facing point of contact for a European web agency — scoping requests, agreeing timelines and budgets, and reporting progress directly to the agency\u0026rsquo;s stakeholders. Translated client briefs into work packages, distributed them across the team, and reviewed output before hand-off; owned quality and delivery commitments end to end. Sustained the engagement for three and a half years on repeat work — every follow-on project won on delivery track record rather than a new pitch. Operated fully remote and asynchronously across time zones, which set the working style later used for APAC pre-sales engagements. Selected Engagements # Full write-ups in Projects.\nEngagement Domain Role AI voice agent call centre platform Logistics tech Solution architect, pre-sales lead Warehouse optimisation platform Electronics manufacturing Solution strategy, PRD, interactive prototype Claims adjudication rules engine POC Health insurance / TPA Architect and hands-on builder Science \u0026amp; Technology Diplomacy Platform Government (Vietnam MOFA) Lead BA / solution owner Edge facial recognition \u0026amp; video analytics Physical security Solution architect, pitch lead Semiconductor AMHS digital twin Semiconductor manufacturing Solution architect Wealth management client portal BFSI / multi-family office Pre-sales architect Mobile banking platform + T\u0026amp;M augmentation BFSI (Vietnam top-10 bank) Pre-sales lead — won, USD 286K Education # Qualification Institution Years Master of Computer Science Universiti Teknologi Malaysia (UTM) 2021 – 2023 Bachelor of Computer Science Oxford Brookes University (top-up) 2019 – 2020 Advanced Diploma, Software Engineering Aptech 2015 – 2017 Bachelor of Business Administration University of Economics, Da Nang 2012 – 2016 Certifications # AWS Certified AI Practitioner (AIF-C01) Professional Scrum Master II (PSM II) — Scrum.org Professional Scrum Product Owner II (PSPO II) — Scrum.org Professional Scrum Master I (PSM I) — Scrum.org Languages # Vietnamese — native English — full professional proficiency Community # 500+ reputation on Stack Overflow; contributor to Project Management Stack Exchange Technical writer on Viblo Asia — 18K+ cumulative views theNextVoz — a third-party VOZ forum client, built solo and published on the App Store and Google Play ","date":"3 August 2026","externalUrl":null,"permalink":"/resume/","section":"Nguyen Hoang","summary":"Nguyen Hoang — AI Solutions Architect \u0026 APAC Pre-Sales Consultant\nDa Nang, Vietnam · hoangtrankhoinguyen@gmail.com · LinkedIn · Download PDF\nSummary # AI Solutions Architect and Pre-Sales Consultant specialising in APAC enterprise pursuits — bridging deep technical architecture (digital twin, voice AI, RAG, computer vision, edge computing) with consultative business outcomes (ODC scaling, market entry, win-rate improvement). Closed SGD 1M pipeline across Singapore and Malaysia, authored 100+ proposals, and architected 15+ enterprise solutions spanning semiconductor manufacturing, travel and aviation, BFSI, healthcare, renewable energy and facility management. AWS Certified AI Practitioner with hands-on full-stack capability — proven by a published mobile app and production-grade systems — that gives every solutioning conversation engineering credibility.\n","title":"Resume","type":"page"},{"content":"","date":"3 August 2026","externalUrl":null,"permalink":"/tags/side-project/","section":"Tags","summary":"","title":"Side Project","type":"tags"},{"content":"In March I started writing a Flutter client for voz.vn, Vietnam\u0026rsquo;s largest tech forum. It has no official public API — the forum runs XenForo and exposes nothing — so the entire data layer is fetch-the-page, parse-the-HTML. As of today, 142 days later:\n374 commits, ~83,000 lines of hand-written Dart (generated code excluded) 34 feature modules, 29 HTML parsers, 78 test files, 897 localised strings Shipped and live on both the App Store and Google Play, currently at 1.4.6 One person, and most of the code written by AI under my direction I am not telling this story to brag about velocity. The opposite: I sat down to write a post about velocity decaying, opened the git log to get my numbers, and discovered I had misread what was happening to my own project.\nWhat I thought was happening # The felt experience was unambiguous. Month one was flight — every evening I sat down, every evening a new screen worked. Month two slowed. By month three, small changes were eating whole evenings.\nCounting commits confirmed it exactly:\nMarch: 154 commits April: 52 May: 27 A 5.7× collapse in three months. The post wrote itself: initial euphoria, then fatigue, then technical debt closing around the throat. Done.\nExcept there were two more months.\nThe git log disagreed # June: 85 commits July: 54 There is no decay curve. June tripled May. So I dug further, this time measuring with something other than how often I typed git commit:\nMonth Commits New files Files touched % new Net lines Del/add Added per commit March 154 248 248 100% +34,000 22% 285 April 52 41 139 29% +7,204 41% 235 May 27 13 78 17% +2,698 47% 188 June 85 105 294 36% +24,985 33% 437 July 54 55 257 21% +14,040 30% 373 Look at the last column. A June commit is roughly 1.5× the size of a March commit. I was not doing less work. I was doing the same work in fewer commits — because later work stopped decomposing into tidy increments.\nCommit count measures how finely work subdivides, not how much work happened. It is a garbage metric, and I nearly built an entire post on top of it.\nThe one column that moves in a single direction # Strip out everything that oscillates and one series tells the real story: new files as a share of all files touched.\n100% → 29% → 17% → 36% → 21% March was 100% — 248 new files out of exactly 248 files touched. Not one line I edited that month was anyone else\u0026rsquo;s, including my own from three weeks prior. No existing constraints, no users, nothing to break.\nThat is precisely the regime where AI is strongest. It is also precisely the regime in which every \u0026ldquo;10x faster\u0026rdquo; number on the internet gets measured.\nFrom April onward, 64% to 83% of the work was editing code that already existed. Even in the June resurgence: 105 new files, but 294 touched — meaning that to insert the new thing, I had to reopen 189 old ones.\nThe work did not shrink. It changed type: from writing to integrating.\nWhy the second half is genuinely harder for AI # Not because the model got worse. For three structural reasons:\nNew code only has to satisfy a description. Existing code has to satisfy every invisible decision already embedded in it. There is a line of configuration in my repo that looks inert: the app sends requests to voz.vn with Dart\u0026rsquo;s default User-Agent. An audit pass proposed replacing it with a Chrome-like string — textbook advice, correct in 99% of projects. Here it made Cloudflare return 403 on every request including the login page, because a Chrome UA emerging from Dart\u0026rsquo;s TLS stack is a well-known bot signature. What cost me a week to diagnose looks, in a diff, exactly like an arbitrary config line. March had no lines like that. July is full of them.\nNew code has a blast radius of zero. Changed code has a radius nobody knows — and the person who knows it most nearly is me, not the model.\nVerification cost scales with the number of people running the previous version. Getting it wrong in March meant fixing it. Getting it wrong in July means somebody loses a half-written post.\nThe real tax is at the convergence points # This is the part that repaid the archaeology. Rank files by how many commits have touched them:\n90 thread_detail/presentation/thread_detail_screen.dart 81 l10n/app_localizations{,_vi,_en}.dart (897 strings) 61 core/router/app_router.dart 49 settings_screen.dart 49 home_screen.dart 46 thread_detail/.../post_card.dart 43 core/constants/storage_keys.dart thread_detail_screen.dart appears in 90 of 374 commits. One commit in four, across the entire project, had to reopen that one file. The router, 61 times. Localisation, 81 — because every feature ends in the same loop of adding strings to both ARB files and regenerating.\nThis is the actual mechanism behind slowdown, and it has nothing to do with technical debt: no new feature is free-standing; each one has to thread through a handful of shared chokepoints. The number of chokepoints does not grow. Traffic through them grows linearly with feature count — so by feature thirty, wiring-into-the-existing-system is larger than building-the-new-thing.\nFor an agent this is the most expensive ground there is. Every time it edits thread_detail_screen.dart, it needs to know why the previous 89 edits did what they did — and it remembers none of them. I remember maybe five, dimly.\nThe slowest month was the most valuable one # May: 27 commits, 13 new files, +2,698 lines. On the table it reads as a lazy month.\nWhat actually happened in May: every database table moved to per-account scoping (schema v4), the multi-account lifecycle was completed, each account got an isolated cookie jar, iPad split-view landed, and so did hinge-aware layout for foldables.\nIt also has the highest deletion-to-addition ratio of any month: 47%. Nearly half the effort was tearing out my own earlier code.\nNo conventional productivity metric rewards May. But without it, multi-account never works, and June never happens.\nThe general form: every easy-to-measure metric rewards accumulation and punishes groundwork — while groundwork is what determines whether you can still move three months later. AI-assisted development sharpens this, because it makes accumulation drastically cheaper while leaving groundwork almost exactly as expensive as it was.\nThe skeleton survived; the flesh was replaced # One more number: of the 248 files I created in March, 220 still exist today — 89%. Even though most of their contents have been rewritten several times over.\nWhich means: first-month code is cheap, but first-month boundaries are expensive.\nThe split between core/ and features/\u0026lt;name\u0026gt;/{data,domain,presentation,providers}, where parsers live, forcing every HTTP request through exactly one client — those calls were nailed down in week one and are still standing four months later. The line-level quality of March\u0026rsquo;s code turned out to barely matter, because it was all going to be replaced anyway.\nFrom which a usable rule: during the phase where you can vibe most freely, the only thing worth stopping to think hard about is module boundaries. It is the only thing you cannot fix later by asking an AI to rewrite it.\nSo what to do # Know which mode you are in, and stop using the wrong process for it.\nGreenfield mode (high % new files): open the throttle. Big prompts, long agent runs, light review. Risk is low — nobody is using it and there is nothing to break.\nIntegration mode (low % new files — i.e. from month two onward, i.e. most of a project\u0026rsquo;s life): narrow the context, point explicitly at the file to imitate, state the invariants that must not break, write the test first, and read anything touching a convergence point yourself.\nChange what you track. Drop commit counts. Watch two things:\nshare of work touching existing code — tells you which mode you are in deletion-to-addition ratio — tells you whether you are paying debt down or taking more on Treat a frequently-touched file as an architectural smell, not a badge. A file appearing in a quarter of all commits is not \u0026ldquo;the important file\u0026rdquo;. It is where every feature queues up and waits.\nClosing # The 10x is real. I had it, and it lives in March: 248 files, 34,000 lines, alone, while holding down a full-time job.\nBut it was measured over the one stretch where the work happened to have exactly the shape AI is best at — new code, no constraints, no users, no convergence points. That stretch lasted a month. The other four were a different job entirely: inserting new things among two hundred existing decisions without breaking any of them.\nAnd there, the advantage shrinks to precisely the extent that you understand your own system.\nAppendix: how I got these numbers # Runs on any repo. Adjust the range and paths. The filter matters enormously — counting generated code makes every one of these figures meaningless.\nFILTER=(\u0026#39;lib/*.dart\u0026#39; \u0026#39;:(exclude)lib/**/*.g.dart\u0026#39; \u0026#39;:(exclude)lib/**/*.freezed.dart\u0026#39; \u0026#39;:(exclude)lib/l10n/app_localizations*.dart\u0026#39;) Commits per month\ngit log --format=\u0026#39;%ad\u0026#39; --date=format:\u0026#39;%Y-%m\u0026#39; | sort | uniq -c Lines added and deleted per month — note the half-open range (--until is the first of the next month), not -31, which silently misattributes work in 30-day months\ngit log --since=2026-06-01 --until=2026-07-01 --numstat --format=\u0026#39;\u0026#39; -- \u0026#34;${FILTER[@]}\u0026#34; \\ | awk \u0026#39;{a+=$1;d+=$2} END {printf \u0026#34;+%d -%d net %+d del/add %d%%\\n\u0026#34;, a, d, a-d, d*100/a}\u0026#39; New files versus files touched — the most important measurement in this post\n# files created during the month git log --since=2026-06-01 --until=2026-07-01 --diff-filter=A --name-only --format=\u0026#39;\u0026#39; \\ -- \u0026#34;${FILTER[@]}\u0026#34; | grep \u0026#39;\\.dart$\u0026#39; | sort -u | wc -l # total distinct files touched during the month git log --since=2026-06-01 --until=2026-07-01 --name-only --format=\u0026#39;\u0026#39; \\ -- \u0026#34;${FILTER[@]}\u0026#34; | grep \u0026#39;\\.dart$\u0026#39; | sort -u | wc -l Convergence points\ngit log --name-only --format=\u0026#39;\u0026#39; -- \u0026#34;${FILTER[@]}\u0026#34; \\ | grep \u0026#39;\\.dart$\u0026#39; | sort | uniq -c | sort -rn | head -15 Appendix: where to doubt this post # n = 1. One person, one app, one domain. This is a description, not a study. My commit habits changed over time, which by itself pushes the lines-per-commit figure upward — though that drift is also part of the phenomenon being explained. An HTML-scraping app carries unusually high maintenance load, because the other side can change its markup whenever it likes and tells nobody. A CRUD app against a stable API would decay more slowly. \u0026quot;% new files\u0026quot; does not distinguish a one-line edit from a full rewrite. It is a crude measure. I still find it far more honest than counting commits. ","date":"3 August 2026","externalUrl":null,"permalink":"/posts/the-10x-was-real-it-lasted-one-month/","section":"Writing","summary":"374 commits, 142 days, one developer, two app stores. What the git log actually says about AI-assisted development, once I stopped counting commits.","title":"The 10x Was Real. It Lasted One Month.","type":"posts"},{"content":"","date":"20 July 2026","externalUrl":null,"permalink":"/categories/enterprise/","section":"Categories","summary":"","title":"Enterprise","type":"categories"},{"content":"","date":"20 July 2026","externalUrl":null,"permalink":"/tags/enterprise/","section":"Tags","summary":"","title":"Enterprise","type":"tags"},{"content":"","date":"20 July 2026","externalUrl":null,"permalink":"/tags/livekit/","section":"Tags","summary":"","title":"LiveKit","type":"tags"},{"content":"Two categories here. Enterprise engagements are client work — architecture, POCs and proposals delivered through CMC Global. Client names are generalised where the pursuit is active or covered by NDA; the technical substance is unchanged. Personal builds are things I shipped on my own time, mostly to stay honest about what modern stacks actually cost to build.\n","date":"20 July 2026","externalUrl":null,"permalink":"/projects/","section":"Projects","summary":"Two categories here. Enterprise engagements are client work — architecture, POCs and proposals delivered through CMC Global. Client names are generalised where the pursuit is active or covered by NDA; the technical substance is unchanged. Personal builds are things I shipped on my own time, mostly to stay honest about what modern stacks actually cost to build.\n","title":"Projects","type":"projects"},{"content":"","date":"20 July 2026","externalUrl":null,"permalink":"/tags/rag/","section":"Tags","summary":"","title":"RAG","type":"tags"},{"content":"","date":"20 July 2026","externalUrl":null,"permalink":"/tags/voice-ai/","section":"Tags","summary":"","title":"Voice AI","type":"tags"},{"content":"","date":"29 June 2026","externalUrl":null,"permalink":"/tags/content-automation/","section":"Tags","summary":"","title":"Content Automation","type":"tags"},{"content":"","date":"29 June 2026","externalUrl":null,"permalink":"/categories/personal/","section":"Categories","summary":"","title":"Personal","type":"categories"},{"content":"","date":"29 June 2026","externalUrl":null,"permalink":"/tags/remotion/","section":"Tags","summary":"","title":"Remotion","type":"tags"},{"content":"","date":"29 June 2026","externalUrl":null,"permalink":"/tags/tts/","section":"Tags","summary":"","title":"TTS","type":"tags"},{"content":"","date":"15 June 2026","externalUrl":null,"permalink":"/tags/digital-twin/","section":"Tags","summary":"","title":"Digital Twin","type":"tags"},{"content":"","date":"15 June 2026","externalUrl":null,"permalink":"/tags/optimisation/","section":"Tags","summary":"","title":"Optimisation","type":"tags"},{"content":"","date":"15 June 2026","externalUrl":null,"permalink":"/tags/product-strategy/","section":"Tags","summary":"","title":"Product Strategy","type":"tags"},{"content":"","date":"15 June 2026","externalUrl":null,"permalink":"/tags/supply-chain/","section":"Tags","summary":"","title":"Supply Chain","type":"tags"},{"content":"","date":"10 May 2026","externalUrl":null,"permalink":"/tags/healthcare/","section":"Tags","summary":"","title":"Healthcare","type":"tags"},{"content":"","date":"10 May 2026","externalUrl":null,"permalink":"/tags/poc/","section":"Tags","summary":"","title":"POC","type":"tags"},{"content":"","date":"10 May 2026","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","date":"10 May 2026","externalUrl":null,"permalink":"/tags/rules-engine/","section":"Tags","summary":"","title":"Rules Engine","type":"tags"},{"content":"","date":"5 April 2026","externalUrl":null,"permalink":"/tags/firebase/","section":"Tags","summary":"","title":"Firebase","type":"tags"},{"content":"","date":"20 March 2026","externalUrl":null,"permalink":"/tags/dart/","section":"Tags","summary":"","title":"Dart","type":"tags"},{"content":"","date":"20 March 2026","externalUrl":null,"permalink":"/tags/mobile/","section":"Tags","summary":"","title":"Mobile","type":"tags"},{"content":"","date":"1 February 2026","externalUrl":null,"permalink":"/tags/business-analysis/","section":"Tags","summary":"","title":"Business Analysis","type":"tags"},{"content":"","date":"1 February 2026","externalUrl":null,"permalink":"/tags/government/","section":"Tags","summary":"","title":"Government","type":"tags"},{"content":"","date":"1 February 2026","externalUrl":null,"permalink":"/tags/open-source/","section":"Tags","summary":"","title":"Open Source","type":"tags"},{"content":"","date":"1 February 2026","externalUrl":null,"permalink":"/tags/platform/","section":"Tags","summary":"","title":"Platform","type":"tags"},{"content":"","date":"15 January 2026","externalUrl":null,"permalink":"/tags/computer-vision/","section":"Tags","summary":"","title":"Computer Vision","type":"tags"},{"content":"","date":"15 January 2026","externalUrl":null,"permalink":"/tags/edge-computing/","section":"Tags","summary":"","title":"Edge Computing","type":"tags"},{"content":"","date":"15 January 2026","externalUrl":null,"permalink":"/tags/nvidia-jetson/","section":"Tags","summary":"","title":"NVIDIA Jetson","type":"tags"},{"content":"","date":"10 January 2026","externalUrl":null,"permalink":"/tags/machine-learning/","section":"Tags","summary":"","title":"Machine Learning","type":"tags"},{"content":"","date":"10 January 2026","externalUrl":null,"permalink":"/tags/node.js/","section":"Tags","summary":"","title":"Node.js","type":"tags"},{"content":"","date":"10 January 2026","externalUrl":null,"permalink":"/tags/quantitative/","section":"Tags","summary":"","title":"Quantitative","type":"tags"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]