In brief
Overview
Jakarta Metropolitan Area
I am a CTO who tends to be handed two problems at once: a technology
programme that is not landing, and an organisation that is not yet
shaped to land it. Most of what follows is the first problem being
solved by fixing the second, because a programme that is late for
structural reasons cannot be rescued by pushing harder on the
schedule.
The work has been in retail, food and beverage, travel and FinOps, at
publicly listed companies, at multinationals and at startups. The
range matters less than the pattern inside it: an ERP or a warehouse
system at the centre, a commerce channel on top of it, and a team who
have to be able to keep both running after I am no longer the person
who understands them.
I have led a global technology team of up to fifty across Indonesia,
Vietnam, Malaysia and the Philippines, and earlier in my career I
built the offshore IT services startups that supply teams like that
one. Both halves matter to how I hire: I have been on the side that
sells capacity as well as the side that buys it.
I still write code, and I would rather demonstrate that than assert
it. The semantic search on the front page of this site is mine end to
end, from the quantisation choice to the accessibility invariants, and
the repository it is built from is public. That is a claim you can
check rather than one you have to take on trust, which is the only
kind worth making about being hands on.
I also work as a fractional CTO: technology strategy, turning around
at-risk projects, and total cost of ownership. The engagements that
suit it best are the ones where an unbiased outside read is worth more
to a board than another pair of hands.
Restaurant Technology Platform
Product Management
Director of Engineering, Yummy Corp
Fast-tracked product–market fit for front and back of house technology
in the restaurant industry. Three systems, built in the order that
let each one pay for the next.
The sequence was the strategy. Going from an MVP to more than a hundred
outlets in six months does not leave room to build three systems in
parallel and integrate them at the end, and it punishes any component
that cannot be rolled out to a live kitchen during service. So each
system had to be independently useful on the day it shipped, and each
one had to make the next cheaper rather than merely possible. That is a
harder constraint than it sounds: it rules out the platform-first
approach where nothing is visible to an operator until the foundations
are finished.
Front of house came first: point-of-sale, kitchen
display system, loyalty programme and real-time analytics. Getting the
transaction layer right early meant every later system had trustworthy
data to read from, rather than a reporting pipeline bolted on after the
fact.
The IoT layer was built with Operations rather than for
them, because the waste it targeted was operational, not technical. An
ESP32-based system handled temperature monitoring, energy metering and
AI-on-the-edge detection, with EMQX as the broker. Inference runs on
the device: a kitchen with intermittent connectivity still needs its
cold storage watched, and paying to stream raw sensor data to the cloud
to answer a question the device can answer itself is a cost with no
matching benefit.
Edge inference is not free, and the price is paid somewhere other than
the cloud bill. Models and firmware have to reach devices sitting
behind a restaurant's network, which means an update path that works
unattended, and a device that decides for itself is a device you cannot
debug by reading a log in one place. I took that trade because the
failure it protects against is the one that actually costs money: cold
storage going out of range during an outage is spoilage, and an alert
that depends on the same link that just failed is not an alert. Where
the question was analytical rather than urgent, the data went to the
cloud and the answer waited.
Menu planning was the piece that needed AI to be worth
anything. It uses an LLM with vector search to query product mix data
and infer location-specific variations — the same dish sells
differently two kilometres apart, and the interesting signal is in that
variation rather than in the aggregate. Retrieval over real product mix
data, not a model asked to guess at a menu.
Retrieval rather than fine-tuning, and that is a cost decision as much
as a quality one. Product mix changes every week; a fine-tuned model
encodes the mix as of the day it was trained and has to be retrained to
learn that a dish stopped selling. Retrieval reads the current numbers
at query time, so the system improves when the data does and there is
no training budget to defend annually. The other half of it is that a
retrieved answer can be traced to the rows it came from, and a
recommendation an operations manager cannot interrogate is a
recommendation they will correctly ignore.
I also took ownership of product management directly, driving the
roadmap for B2B value-added services and loyalty features. Owning the
roadmap rather than receiving it is what made the sequencing above
enforceable: the order systems get built in is a product decision
before it is an engineering one, and a CTO who only holds the
engineering half of it can advise on that order but cannot hold it.
- From MVP to 100+ outlets in 6 months
- Increased RPR
Ghost Kitchen Startup
Technology Strategy Optimization
Director of Engineering, Yummy Corp
The platform worked but the unit economics did not scale: cost per
outlet was not falling as outlets were added. Refactoring the entire
technology platform was the only way to change that shape, so it was a
cost-structure problem before it was an engineering one.
Cost per outlet is the number that decides whether a ghost kitchen
business works, and it is the one a technology organisation can move
without anybody in the kitchens changing what they do. If each new
outlet brings its own licence, its own integration and its own share of
an operations team, the technology is a variable cost wearing a fixed
cost's clothing, and growth makes the problem larger rather than
cheaper. Every decision below was chosen against that single test:
does this make the hundredth outlet cheaper than the tenth.
Migrating AWS to GCP and repurchasing cloud-native ERP.
Repurchasing rather than migrating the existing ERP was the harder call
and the right one — carrying a self-managed system into a new
environment would have moved the licence and operational burden intact
rather than removing it.
Then developer experience, treated as a cost lever rather than a
perk. GitHub Actions, Terraform and Go, leaning on managed GCP
services wherever running something ourselves earned nothing. Release
cycle time is the metric that compounds: everything downstream of it
gets cheaper when it drops.
And the org chart, because the expense line is mostly
people. Trainee and upskilling programmes to build capability
in-house, with outsourcing reserved for genuinely specialised work.
Buying permanent headcount for a temporary specialism is how technology
budgets quietly ratchet upward.
An 80% reduction is not one saving, and it is worth being precise about
that rather than letting the figure imply a single clever move. It is a
licensing model replaced, a self-managed estate handed to managed
services, an outsourcing line brought in-house, and a release process
that stopped consuming people. None of those individually gets close.
They compound because each one removes work the next one would
otherwise have had to keep paying for, which is also why the order
mattered: doing the org chart first would have meant training a team to
operate infrastructure I was about to delete.
- 80% reduction in ICT-related expenses
- 50% faster release cycle
Multinational Retail Company
Digital Transformation
Chief Technology Officer, Sophie Paris Indonesia
A B2B2C e-commerce transformation three years behind schedule, and a
USD 3 million ERP and WMS migration that was not going to land. The
first job was triage.
The rescue turned on scope, not delivery speed. The
programme was replacing ERP and WMS together. I implemented the new WMS
and kept the legacy ERP for financials and manufacturing — the
warehouse was where the pain and the return actually were, and the
financial modules were working. That split is what realised the ROI on
a project already written off, and it is the decision I would point to
first: the fastest way to finish was to stop doing part of it.
The hard part of that decision was not technical. A programme three
years in has a sunk cost that everyone can name and a set of
commitments people have already defended in front of a board, so
proposing to deliver less than was promised reads as conceding failure
at exactly the moment nobody wants to. What made it possible to carry
was separating the two systems on evidence rather than on preference:
the warehouse was where the operational pain and the measurable return
both sat, and the financial modules were not the thing anyone was
complaining about. Descoping the part that was working is easier to
argue than descoping the part that is late.
Re-engineering the IT function was the other half. A
programme that has missed for three years is usually not staffed
wrongly so much as organised to produce reports about delivery instead
of delivery. Changing who decided what, and shortening the distance
between a problem being seen and being fixed, is what let a nine-month
plan be credible rather than optimistic. The same team largely
delivered it.
The transformation then completed in nine months after
three years of not completing, on an IT function re-engineered to
deliver rather than a longer timeline.
From there the work was compounding rather than corrective: refactoring
the distributor point-of-sale system; seamless omnichannel UX across
e-commerce, point-of-sale and loyalty, which is what moved customer
lifetime value; and consolidating disparate sales, stock and assortment
data into PowerBI dashboards to give a distributor 360 view — the
reporting nobody could assemble while the data sat in separate systems.
Finally, harmonising IT systems across affiliates in Vietnam, Malaysia
and the Philippines with a global cross-functional team, so regional
expansion had something to expand onto. Social commerce across
Indonesia, Vietnam and the Philippines scaled to 1.5 million monthly
active users.
- Completed in 9 months, after three years behind schedule
- Realised the USD 3 million ROI
- Scaled to 1.5 million MAU across three markets
Browser-Local Semantic Search
Applied AI
This site
The search on the front page of this site answers questions about
these projects by running a sentence embedding model inside the
visitor's own browser.
There is no inference server, no API key and no request carrying the
question anywhere. It is small, and it is deliberately small: the
point was to build the thing end to end rather than describe having
once specified it.
all-MiniLM-L6-v2, quantised to 8-bit, executed by ONNX Runtime
on WebAssembly through Transformers.js. Quantisation is what
makes the model shippable at all — full precision is four times the
weight for a retrieval quality difference this corpus cannot resolve.
The runtime runs single-threaded because GitHub Pages cannot send the
COOP and COEP headers that SharedArrayBuffer requires, so
the threaded build would silently fall back anyway. I measured
crossOriginIsolated in the deployed page rather than
assuming it.
The model, the runtime and the weights are all served from this
origin. The obvious build fetches them from a model hub on
first use. That would mean pinning a CDN script by SRI digest in one
breath and then pulling tens of megabytes of unpinned executable
WebAssembly from a third party in the next — the same integrity
problem an order of magnitude larger. Vendoring costs repository size
and buys a page with no third-party requests at all, which I verified
in the network panel rather than in the source.
Retrieval is an exhaustive cosine scan, not an approximate
index. A few dozen passages at 384 dimensions is under ten
thousand multiply-accumulates — microseconds, and four orders of
magnitude below the cost of embedding the question that precedes it.
An HNSW graph would add a dependency, a build artefact and a recall
tradeoff to optimise the part that is already free. Knowing where that
crossover sits is the engineering; reaching for the vector database
before it is the failure mode.
The index is generated by a page, not by a script.
Embeddings are precomputed and committed, because asking every
visitor's device to embed the whole corpus before answering the
first question is a cost paid thousands of times to save paying it
once. What that buys is a way for the index to drift from the prose
it describes, so the generator runs in a browser, against the same
vendored runtime and weights the site ships, which makes the vectors
the ones the live code would have produced by construction. A build
on a server could not promise that: outside a browser the runtime's
backend registry is empty, and a vector computed by a different
stack does not raise an error, it just retrieves worse. A check in
CI then fails the build if any committed passage stops appearing on
this page.
Where this approach stops working, which is the part worth
knowing. It is bounded by the download, not by the search.
Twenty megabytes is a defensible one-time cost on a page someone chose
to interrogate, and it would be indefensible on a page that had to
answer before the visitor asked for anything. The linear scan holds to
a few thousand passages on this hardware; past that the crossover with
an approximate index finally arrives and the honest move is to take the
dependency I argued against above. And a 384-dimension general-purpose
embedding retrieves topics well and proper nouns poorly, so a question
naming one specific system is better served by find-in-page on the
portfolio. Knowing which of those limits is nearest is the difference
between shipping this here and shipping it everywhere.
The accessibility constraints shaped the code more than the
model did. The load button cannot use the disabled property,
because disabling the control somebody just pressed moves keyboard
focus to the document body, and here it would strand them there for the
length of a multi-second download. It sets an ARIA state and guards
re-entry with a flag instead. Results are announced through a live
region, because focus deliberately stays where the visitor put it.
These are the decisions that never show up in a demo and entirely
decide whether anyone can use the thing.
- No inference cost and no data egress — the
question never leaves the tab
- ~25ms per query after a one-time model load
- Zero third-party requests at runtime
Leading the team
Engineering Leadership
Teams of up to fifty, across four markets
A global technology team of up to fifty, distributed across Indonesia,
Vietnam, Malaysia and the Philippines. Distributed across markets is a
different problem from distributed across cities: the teams were
attached to affiliates with their own systems, their own regulators and
their own commercial priorities, so the work was not only building
software together but agreeing what was genuinely shared and what only
looked shared. Harmonising systems across those affiliates was as much
an organisational negotiation as a technical migration.
Build capability rather than buy it, with a stated exception.
Trainee and upskilling programmes were how the ghost kitchen cost
structure actually changed, and they are the part of that story I would
defend hardest, because they are the part that kept paying after I
left. Outsourcing was reserved for genuinely specialised work: a
specialism you need once does not justify permanent headcount, and
hiring for it anyway is how a technology budget ratchets upward in a
way nobody can later point at. Having built offshore IT services
businesses earlier in my career, I have sat on the vendor side of that
conversation too, which makes me harder to sell to.
Measure the delivery system, not the developers. DORA
metrics, read as properties of the pipeline rather than as a
scoreboard. Release cycle time is the one I watch first because it
compounds: everything downstream of a shorter cycle gets cheaper, and a
team that can ship on a Tuesday afternoon makes different and better
decisions than one that batches for a monthly window. When those
numbers get used to rank individuals they stop measuring anything, so
that is a line worth holding explicitly.
I read the diffs, and I am careful about what that is for.
Staying close to the code is how I keep an accurate model of what is
expensive, which is what makes an estimate arguable rather than
accepted on authority. It is not a licence to review my way into other
people's work. The distinction matters: a CTO who reads code to stay
calibrated is useful, and one who reads it to stay in control is a
bottleneck with a title.
How I decide
Operating Principles
Drawn from the projects above
These are not a philosophy written in advance. They are what the four
projects above have in common, noticed afterwards, which is the only
honest way to arrive at a principle.
Find the cost structure before writing the plan. The
ghost kitchen looked like a platform refactor and was a unit economics
problem; the retail programme looked like a delivery problem and was a
scope problem. In both cases the technical plan that follows from the
right diagnosis is unrecognisable from the one that follows from the
wrong one, and no amount of execution quality recovers from starting on
the second.
Descoping is a delivery technique. The fastest way to
finish a programme that is years late is usually to stop doing part of
it. This is unpopular because it looks like retreat, so it has to be
argued on evidence about where the return actually sits, and it has to
be argued early enough that the saving is real.
Prefer the boring component and justify the interesting one.
Managed services where running it ourselves earns nothing, an exhaustive
scan where a vector database would be slower, retrieval where
fine-tuning would need a budget line every year. The bias is not against
sophisticated tools; it is that a sophisticated tool has to beat the
simple one on a number I can name before it arrives, not after.
Measure the thing rather than assume it. I checked
whether cross-origin isolation was available in the deployed page
before concluding threads were unavailable, and I read the transfer
sizes off the network panel rather than off the files on disk. Most
architecture arguments are settled by one measurement that nobody
bothered to take, and taking it is cheaper than winning the argument.
Leave it maintainable by whoever is next. A system that
only works while its author is present has not been finished. This site
is the small version of the same instinct: no build step and no package
manager, so it is still editable years from now without reviving a
toolchain, and every invariant that would be easy to break by accident
is enforced by a check rather than written in a document nobody
rereads.
Now
Fractional CTO & Technology Strategy
Launching a portfolio of products across FinOps, F&B and retail, and
fast-tracking product–market fit from agentic AI and SaaS through to
IoT.
Also available for fractional CTO work: technology strategy, turning
around at-risk projects, and total-cost-of-ownership optimisation —
technology leadership on an as-needed basis, and an unbiased outside
perspective.
In practice that covers SaaS and custom software development, IT
consulting, information management, project management and strategic
planning, and it is usually one of three situations: a board that needs
an independent read on a programme it is being reassured about, a
company whose technology spend has grown faster than its technology,
or a founding team who need someone senior enough to say which half of
the roadmap to delete. The common thread is that the useful thing is a
decision, not capacity.
The agentic AI work is current rather than historical, and it is
hands-on. The search on this site is the smallest publishable piece of
it: local inference, retrieval over a real corpus, and a set of
deliberate refusals about what to add. Building at that level is what
keeps me able to tell the difference between a capability and a demo,
which is most of what a board is paying a CTO for at the moment.
Skills
- Product Management
- Agile, DORA
- AI & Data
- Agentic AI (LangGraph, Google ADK, n8n), Python, BigQuery
- Engineering
- Go (microservices), TypeScript (React, Next.js, Playwright),
Flutter (Firebase), SQL
- DevOps
- GitHub Actions, Terraform, GCP (Cloud Run, Pub/Sub, PostgreSQL), Redis
- ERP
- Financial, Order and Supply Chain — inventory, warehouse and manufacturing
Earlier
Before the CTO roles: leading IT functions, delivering projects and
writing code, including building offshore IT services startups.
The substance of it was ERP implementation, B2B2C e-commerce operations
and omnichannel initiatives at publicly listed and multinational
companies, then technology strategy for startups. That order turns out
to matter. Having implemented ERP rather than only commissioned it is
why the retail rescue could be scoped confidently: knowing which
modules are genuinely entangled and which merely appear to be in the
vendor's diagram is not something you can acquire from a status
report.
It started in code, as a programmer and then a systems analyst, which is
the part I have never fully left. Every role since has been further
from the keyboard by title and closer to it in practice than the title
suggests.
- Head of Information Technology
Panorama Transportasi Tbk
- IT Manager
Panorama Sentrawisata Tbk
- Project Manager
GlobalTech Computer Konsultindo
- System Analyst
Robat in’t Veld Formatie bv
- Computer Programmer
Stuppa Indonesia
← Back to home