Skip to content
TT
Open to senior & staff roles

I build headless commerce that loads fast and converts better.

I'm Thang — a senior Shopify and full stack engineer with 9+ years shipping production commerce. Most recently a 300,000-product headless Shopify bookstore for Simon & Schuster across US and UK, and a WooCommerce store holding 20–30 orders a minute at peak.

Vietnam · GMT+7English · VietnameseRemote-first
ShopifyHeadless ShopifyStorefront APIAdmin APIBuy Button SDKNext.jsReactTypeScriptNode.jsNestJSAWSDockerPostgreSQLRedisCypressGA4GTMCROShopifyHeadless ShopifyStorefront APIAdmin APIBuy Button SDKNext.jsReactTypeScriptNode.jsNestJSAWSDockerPostgreSQLRedisCypressGA4GTMCRO
About

Nine years of shipping commerce that has to stay up.

I'm a full stack engineer who specialised into commerce — specifically the part where a storefront meets a platform and things get difficult. Headless Shopify at 300,000 products. WooCommerce at 20–30 orders a minute. An app that installs natively on three platforms with incompatible checkout models.

The work I'm best at sits on the seams: the Storefront API boundary, the checkout hand-off, the inventory sync that silently drifts, the event pipeline that must never pay a partner twice. These are the problems that look small in a ticket and turn out to be the whole project.

I care about what happens after launch. Conversion data, Core Web Vitals on real devices, and Cypress coverage on the paths that cost money when they break — because a storefront that ships and then quietly loses 3% of its checkouts is not a successful project.

EnglishVietnameseVietnamGMT+7Open to senior & staff roles

Checkout is sacred

I hand checkout back to Shopify rather than rebuilding it. A custom checkout costs more in PCI scope, payment methods and lost Shop Pay conversion than it will ever earn back.

Measure before optimising

On a store doing 20–30 orders a minute, the obvious fix was caching the catalogue. The actual bottleneck was the order-write path. Profiling first is not process — it is the difference between fixing it and not.

Assume every event arrives twice

Webhooks retry, pipelines redeliver, users double-click. Idempotency is not a nice-to-have on money paths — it is the design.

Ship the trade-off, not the ideology

Headless is a trade: rendering control for routing, caching and preview complexity. I go headless when the catalogue or the experience demands it, and stay on a theme when it does not.

Open to

Senior Shopify DeveloperSenior Full Stack EngineerSolutions EngineerPlatform EngineerShopify Plus Consultant
Selected work

Five projects, and what was actually hard about each.

Every case study covers the problem, the architecture, the parts that went wrong, and what changed for the business.

Shopify expertise

What I actually mean when I say I know Shopify.

Not a badge list. Each of these is a decision I have had to make on a production store, and the reasoning behind it.

Headless Shopify

Shopify keeps the commerce. You get full control of rendering, routing and caching.

Going headless is a trade, not an upgrade. You gain rendering control, edge caching and a component model that a Liquid theme cannot give you — and you take on routing, cache invalidation, preview and a checkout you no longer own end to end. I have shipped this on a 300,000-product catalogue across two regions, which is where the trade actually gets tested: the moment your catalogue outgrows what a theme can paginate, headless stops being a preference and becomes the requirement.

What you get

A storefront whose performance ceiling is set by your architecture rather than by theme limits.

Storefront API

The customer-facing read path — products, collections, cart.

The Storefront API is deliberately scoped to what a customer may see and do. The engineering that matters is in the shape of your queries and the boundaries of your cache: over-fetch and every page pays for it, under-fetch and you waterfall. At 300k products, cursor pagination has to be treated as a streaming problem with cached boundaries rather than a list you can walk on demand.

What you get

Fast catalogue and cart surfaces that stay fast as the catalogue grows.

Cursor pagination that stays cheap at catalogue scale
query CollectionPage($handle: String!, $cursor: String) {
  collection(handle: $handle) {
    products(first: 24, after: $cursor) {
      pageInfo { hasNextPage endCursor }
      nodes {
        id
        handle
        title
        featuredImage { url altText width height }
        priceRange {
          minVariantPrice { amount currencyCode }
        }
      }
    }
  }
}

Admin API

Everything the storefront is not allowed to do.

Inventory reconciliation, metafield-driven merchandising, bulk catalogue operations, order back-office work. The Admin API is where rate limits become a design constraint rather than a footnote — Shopify's cost-based throttle means a naive bulk job dies halfway through and leaves you in a partial state. Bulk operations and idempotent, resumable jobs are the difference between a sync that works and a sync that works on a small store.

What you get

Catalogue and inventory operations that survive 300k products and partial failure.

Respecting the cost-based rate limit instead of hoping
async function adminRequest<T>(query: string, variables: object): Promise<T> {
  const res = await shopify.request(query, variables);

  // Shopify returns the leaky-bucket state on every call. Slow down
  // *before* being throttled, not after a 429.
  const { currentlyAvailable, maximum } = res.extensions.cost.throttleStatus;
  if (currentlyAvailable < maximum * 0.2) {
    await sleep(1000);
  }

  return res.data;
}

Buy Button SDK & checkout

Hand checkout back to Shopify. Deliberately.

Checkout is the one surface where building your own costs far more than it earns — PCI scope, payment methods, fraud, tax, and Shop Pay conversion rates you will not beat. The Buy Button SDK lets a headless storefront hand off cleanly. The real skill is debugging the boundary: when a hand-off fails, the failing surface belongs to Shopify, so you diagnose it with pixel and network-level evidence to separate your bug from platform behaviour.

What you get

Shopify's conversion-optimised checkout, with hand-off failures that are diagnosable rather than mysterious.

Custom Pixel

Accurate checkout events in a sandboxed world.

Since Shopify moved pixels into a sandbox, the old approach of injecting scripts into checkout is gone. A Custom Pixel subscribes to Shopify's standard event stream from inside that sandbox — which means your analytics gets trustworthy `checkout_completed` and `purchase` events instead of the inferred, lossy ones that make every funnel report an argument.

What you get

A funnel report the marketing team can actually make decisions from.

Custom Pixel: forwarding a real purchase event to GA4
analytics.subscribe("checkout_completed", (event) => {
  const checkout = event.data.checkout;

  gtag("event", "purchase", {
    transaction_id: checkout.order.id,
    value: checkout.totalPrice.amount,
    currency: checkout.currencyCode,
    items: checkout.lineItems.map((item) => ({
      item_id: item.variant.sku,
      item_name: item.title,
      price: item.variant.price.amount,
      quantity: item.quantity,
    })),
  });
});

GA4 & GTM

Instrumentation that survives ad blockers and consent.

GA4's event model is a genuine break from Universal Analytics, and most stores are still reporting badly because of it. I set up GTM as the single control plane, define the ecommerce event schema once, and wire it through both the storefront and the Custom Pixel so client-side loss and consent state are accounted for rather than quietly discarded.

What you get

Attribution and funnel data you can defend in a meeting, not numbers that disagree with Shopify's own reports.

Performance

Core Web Vitals on real devices, not on your laptop.

Storefront performance is mostly a discipline of not shipping things: image weight, third-party tags, hydration cost, and render-blocking work in that order. On commerce sites the biggest wins are usually LCP image handling and getting the marketing tag stack under control — a store can have perfect application code and still fail Core Web Vitals because six tags load synchronously in the head.

What you get

Faster storefronts, better organic ranking signals, and fewer people leaving before the page renders.

Conversion optimisation

Shipping is half the job. Knowing if it converts is the other half.

Speed is a conversion lever, but only one. The rest is in the funnel: where carts are abandoned, which variants confuse people, what the checkout hand-off costs you. With the funnel properly instrumented, CRO stops being redesign-by-opinion and becomes a sequence of changes you can actually measure.

What you get

Changes justified by funnel data instead of by taste.

Cypress E2E

The tests that exist because something expensive broke once.

On a commerce site you do not need to test everything — you need to test what costs money when it breaks. Add to cart, checkout hand-off, region switching, inventory display. Those run in CI on every change, because the alternative is finding out from a customer that checkout has been broken since Tuesday.

What you get

Revenue-path regressions caught before deploy, not after a lost sale.

Guarding the checkout hand-off boundary
it("hands off to Shopify checkout with the correct cart", () => {
  cy.visit("/products/the-midnight-library");
  cy.findByRole("button", { name: /add to cart/i }).click();

  cy.findByRole("link", { name: /checkout/i }).click();

  // The hand-off is the boundary that breaks in production.
  cy.origin("https://checkout.shopify.com", () => {
    cy.contains("The Midnight Library").should("be.visible");
  });
});
Experience

The path from full stack generalist to commerce specialist.

06

Remote · US & UK storefronts

Simon & Schuster

Senior Shopify / Full Stack Engineer

Headless Shopify storefronts for a 300,000+ product publishing catalogue across two regions.

  • Built the storefront on the Shopify Storefront API with Next.js, replacing theme-bound rendering.
  • Ran catalogue and inventory operations through the Admin API at 300k-product scale.
  • Kept Shopify checkout via the Buy Button SDK and made hand-off failures diagnosable.
  • Instrumented the funnel with GA4, GTM and a Shopify Custom Pixel.
  • Covered revenue-critical paths with Cypress E2E in CI.
ShopifyStorefront APIAdmin APINext.jsCypressGA4
Read the case study

05

Remote

Cost Price Supplements

Senior Full Stack Engineer

Performance, reliability and integration work on a store peaking at 20–30 orders per minute.

  • Profiled and relieved the order-write contention that limited peak throughput.
  • Introduced Redis caching and session handling on the hottest paths.
  • Built continuous, idempotent warehouse stock reconciliation.
  • Shipped Luigi's Box AI search and event-driven marketing automation.
WooCommercePHPRedisMySQLCypress
Read the case study

04

Remote

Order Protection

Senior Full Stack Engineer

Shipping-protection app with subscription billing, shipped natively to Shopify, Magento and BigCommerce.

  • Designed a platform-agnostic core with thin per-platform adapters.
  • Built the Shopify app properly: OAuth, session tokens, webhooks, embedded surfaces.
  • Made webhook processing idempotent to eliminate duplicate-charge bugs.
  • Handled subscription billing and per-order premium reconciliation.
Shopify AppNode.jsReactPostgreSQLPayments
Read the case study

03

Remote

Affitor

Senior Full Stack Engineer

Affiliate platform with cross-domain attribution and an idempotent event-processing pipeline.

  • Rebuilt attribution to work without third-party cookies.
  • Achieved exactly-once accounting on an at-least-once event pipeline.
  • Deployed containerised services to AWS ECS with Redis-backed hot lookups.
Node.jsNext.jsAWS ECSRedisDocker
Read the case study

02

Remote

ShowdownTV

Full Stack Engineer

Live streaming platform on AWS MediaLive and CloudFront with Redis-backed live state.

  • Delivered adaptive-bitrate live video through MediaLive and CloudFront.
  • Absorbed start-of-stream traffic spikes through CDN and cached state.
Next.jsNode.jsAWS MediaLiveCloudFrontRedis
Read the case study

01

Vietnam

Earlier engagements

Full Stack Engineer

Commerce and web application work across the JavaScript and PHP ecosystems — the foundation the Shopify specialisation was built on.

  • Shipped production commerce features across multiple platforms and teams.
  • Moved from general full stack work into deep commerce-platform specialisation.
JavaScriptReactNode.jsPHPMySQL
Technical skills

The stack, grouped by what I'd be trusted to own.

Highlighted items are where I have the most production depth — the rest I use comfortably.

Commerce Platforms

Where most of the last nine years went. Shopify deeply, plus the platforms merchants actually migrate from.

ShopifyHeadless ShopifyShopify PlusStorefront APIAdmin APIBuy Button SDKShopify FunctionsLiquidWooCommerceBigCommerceMagento

Frontend

Storefronts that render fast on real devices and real networks, not just on a laptop.

ReactNext.jsTypeScriptApp RouterTailwindCSSCore Web VitalsAccessibility

Backend & APIs

The services behind the storefront — integrations, event processing, and the money paths.

Node.jsNestJSREST & GraphQLWebhooks & idempotencyEvent processingPHP

Infrastructure & Data

Enough platform depth to own a deploy, a queue and a database — not just consume them.

AWSAWS ECSCloudFrontDockerPostgreSQLRedisMySQLCI/CD

Analytics & Growth

Shipping a storefront is half the job; knowing whether it converts is the other half.

GA4Google Tag ManagerShopify Custom PixelConversion optimisation (CRO)A/B testingFunnel analysis

Quality

The tests that exist because something expensive broke once.

CypressE2E testingPerformance profilingCheckout debuggingMonitoring
Achievements

The numbers, and the things behind them.

0+

Years shipping production software

Commerce platforms, APIs and infrastructure since 2016.

0K+

Products served headlessly

The Simon & Schuster catalogue, across US and UK storefronts.

0/min

Peak order throughput handled

Sustained without checkout degradation on a high-traffic store.

0

Commerce platforms shipped natively

Shopify, Magento and BigCommerce from one product core.

Shipped headless commerce at publishing scale

Took a 300,000-product catalogue headless across two regions without a big-bang cutover, on a store that was transacting the entire time.

Made a headless checkout debuggable

Built the pixel and network-level evidence trail that separates your bugs from Shopify's behaviour — the single hardest part of running headless in production.

Held stock accuracy at 20–30 orders per minute

Continuous, idempotent warehouse reconciliation on a WooCommerce store selling faster than its sync was designed for.

Exactly-once accounting on an at-least-once pipeline

Idempotent event processing for affiliate attribution, where a duplicated event is a real overpayment to a partner.

One product, three commerce platforms

A platform-agnostic core with thin adapters, so Shopify, Magento and BigCommerce ship the same feature once.

Cross-domain attribution after third-party cookies

Rebuilt affiliate attribution on first-party mechanisms when the industry default stopped working.

Contact

Let's talk about
your storefront.

I reply to every message that isn't a template. If you're hiring for a senior Shopify or full stack role — or you have a headless build that's gone sideways — tell me what you're working on.

Based in Vietnam (GMT+7) · Working remotely with US, UK and EU teams

Goes straight to my phone. I reply to every real message.