Tillwire Read the guide
New A new generation of ecommerce engine

The whole shop.
One engine.
No add-ons.

Tillwire runs a complete online shop from one Go program: catalogue, checkout, payments, couriers, orders, mail and a full back office. Extend it without limit. Put any frontend on it. Run it on your own server.

259API operations 23event types 1binary
yourshop.example/ridge-blend
250 g

Ridge Blend, whole bean

R 145,00R 165,00

An illustration with example data. Try the sizes: the third box shows how a size that cannot be bought looks.
On the wire
  • order.placed
  • order.paid
  • order.packed
  • order.shipped
  • order.delivered
  • order.cancelled
  • order.refunded
  • shipment.in_transit
  • shipment.out_for_delivery
  • shipment.ready_for_collection
  • shipment.delivered
  • stock.low
  • product.created
  • product.updated
  • product.review.approved
  • product.review.sent_back
  • product.review.look_again
  • product.review.photo_asked
  • product.review.retired
  • picture.approved
  • picture.rejected
  • picture.version_requested
  • customer.created
In the box

Everything a real shop needs. Built in, not bolted on.

On large hosted platforms, much of a real shop comes from add-ons, each with its own fee and its own idea of your data. In Tillwire the core is one engine, one database and one set of rules.

Checkout that never surprises

Guest checkout with no passwords. Stock held while the buyer pays. The delivery price follows the address, and the buyer sees the total before every charge.

CartDetailsDeliveryPay
Total to payR 244,00

Payments, one port

Card gateways, bank transfer, cash on delivery and gift cards. Keys stored encrypted.

CardBank transferCash on deliveryGift card

Live courier rates

Rates, pickup points, booking, labels and tracking, through one courier port.

Locker2 days
Door to door1 day
Pickup pointnearest first

A real catalogue

Up to 3 options a product, custom fields, a media library, and review before a product goes live.

250 g500 g1 kg

Search and collections

Full-text search with filters and suggestions; collections by hand or by rules.

Ridge Blend, whole beanRidge Blend, ground

Mail that sells

Order mail, consent, segments, campaigns, A/B subject lines and automatic flows.

Cart left aloneWait, then checkSend a reminder

A back office your team can share

A full /admin for orders, catalogue, stock, marketing and mail. Staff roles with rights per screen and per act, and a refusal page that names the missing right.

OrdersChangeCatalogueSeeStore settingsNone

Orders and stock, from events

Order states built from events, refunds, tax invoices and credit notes. Stock by location with a ledger, stock-takes and transfers.

Receipt+24
Order #1042−2
Stock-take±0
See every feature and its state
Counted in the code

Big surface. Small footprint.

259API operations: the same operations the back office uses
31token scopes, each one an exact match
23event types, as a feed and as signed webhooks
0lines of storefront CSS in the engine: the look is the theme’s

Counted on main on 21 October 2026, from the OpenAPI file, the operations contract and the event list.

Extend without limit

Your code. Our updates. No conflict.

Keep your own code in your own folder and never edit an engine file, so each upstream update merges cleanly. Four public doors, each with a written contract and a test that keeps it true.

/api/v1

Operations API

259 operations, idempotent writes, one error format, OpenAPI 3.1.

webhooks

Events

23 types as a feed, or as signed webhooks with retries and replay.

engine/ext

Extension API

Your tables, /admin screens, rights, approval checks, picture holds.

courier/1

Courier connectors

A courier as your own HTTP service, proved by one command.

See a feature added in four files

API

# read products with a scoped token
curl -H "Authorization: Bearer ecl_…" \
  "https://yourshop.example/api/v1/catalogue/products?limit=2"

# the description of every operation, no token
curl https://yourshop.example/api/v1/openapi.json

Use code in an error, not the message: the codes are stable and the list only grows.

Webhook

// Ecl-Signature: t=<unix>,v1=<hex HMAC-SHA256>
t, sig := parseSignature(r.Header.Get("Ecl-Signature"))
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(t + "." + string(body)))
if !hmac.Equal(mac.Sum(nil), sig) {
  w.WriteHeader(401); return
}
// a repeat has the same Ecl-Event-Id: skip it

8 tries with a growing wait, a delivery log, replay and secret rotation.

Extension

func init() {
  ext.RegisterMigrations("acme-notes", sql)
  ext.RegisterRight("acme-notes", ext.Right{
    Name: "edit", Group: "catalogue",
    Label: "Edit product notes",
  })
  ext.RegisterAdmin(ext.Module{
    Name: "acme-notes", Title: "Product notes",
    Right: "edit", Menu: true, Handler: notes,
  })
}

With nothing registered, the engine does not change: a test proves it.

Theme

{{/* product page: your layout, the engine's form */}}
<h1>{{.Product.Name}}</h1>
{{engine.AddToCartForm . "options" "boxes"}}

# check it before you ship
engine storefront check --templates theme

The engine refuses a theme that breaks the contract, and names each problem.

Any frontend

One engine. Any look.

The engine decides what a page says and does. Your theme decides how it looks. Between them is a versioned contract, checked when the engine starts, so a new look cannot break a payment.

A plain, type-first theme
A warm, editorial theme
A loud, playful theme

Illustrations of three looks for the same product data. The engine ships no storefront CSS.

Read about themes and the contract
Built to run

One binary. One database. Backed up while it runs.

No cluster to tend. Tillwire runs on any host with a disk, a port and an S3-compatible bucket.

your frontend

Theme or app

  • Templates on the contract
  • Or your own app on the API
engine

One Go binary

  • Shop, checkout, /admin, API
  • Mail, webhooks and jobs in workers
  • SQLite in WAL mode
bucket

S3-compatible bucket

  • Litestream copies without a pause
  • A new host restores at start
  • A weekly restore drill
Read how to run it
For the sceptics

Measured, not promised.

One engine on 8 cores, a store with 50,000 products and 500,000 orders, and no CDN in front. These are the numbers, with where it stops.

54buyers a second

through the whole checkout, from add to cart to the paid order page. p95 under 9 ms. 5,489 orders paid in 3 minutes, and no limit reached.

3.6msp95, home page

at 135 requests a second, and still no limit reached. Product and category pages: 0.3 to 8 ms each.

114requests a second

where a realistic mix of shop and back office pages passes 500 ms. Buyers shed at that point: 0.

130mails a second

flat for 15 minutes in a mailing to 160,000 contacts: about 21 minutes for all of it. The mailing’s 160,000 mails were ready in 18 s.

0.2ssign-in mail, p50

while that mailing runs: order and sign-in mail go first. Cart writes stay at 7 to 8 ms.

500MiB of memory

for the engine at the end of the full load test.

Measured on 21 October 2026 on main, with k6 and the project’s perf runner: a 16-core cloud server, the engine pinned to 8 cores and the load generator to the other 8. A test store of 50,000 products, 150,000 variants, 500,000 orders and 200,000 contacts. No CDN, no TLS, a test payment gateway, mail to a local test server. “p95” means 95 of 100 requests were faster.

Where it stops today

The limit is the CPU that renders pages on one server, not the database. Some /admin screens are slow at this volume (the catalogue list takes 5.4 s); the fixes are planned. By calculation from these numbers, not a test: with a CDN that keeps 9 of 10 public pages, a sale at 50 times the traffic of a store with 5,000 visitors a day sends the engine 10 to 25 requests a second, well under the 114 measured.

What comes next Planned

Today one engine runs one store. The planned next step: extra read-only engines on a copy of the database, behind a load balancer, for the public pages. It is a future project, not yet scheduled.

See the full numbers and the plan to scale out
Honest by design

Every claim is on main today.

This site is checked against the code. A feature that is planned says “Coming”. A number appears only when it was counted or measured, with its method.

See what is on main, off by default or coming
  • No passwords for buyers: a link or a 6-digit code
  • Checkout works without JavaScript
  • Secrets never in the config file
  • A Content-Security-Policy by hashes only
  • Data export and erasure for every buyer
  • Analytics that store no IP address

Build your next shop on Tillwire.

Run a demo store on your own computer in three commands, then open the guide.