One binary. One database. One file of settings.
Tillwire runs on any host with a disk, a port, environment variables and an S3-compatible bucket. The shape is small on purpose, so a shop is easy to run, copy and restore.
Four parts. Nothing else to tend.
theme/One theme folder
- Checked against the contract at start
engineOne Go binary
- Shop, checkout, payments, couriers,
/admin - Mail, webhooks and jobs in workers
- A container image is built from it
engine.dbOne SQLite database
- In WAL mode, in the data folder
- Only the engine reads or writes it
Settings in a file. Secrets never.
One configuration file holds the store’s settings. Each secret is only a pointer to the environment or to a file, so the file is safe to keep in git.
An excerpt with keys from the integration guide. The engine checks every key at start.
store: base_url: https://yourshop.example environment: test api: rate_per_min: 60 # per token events_days: 30 webhooks: max_endpoints: 20 log_days: 30 secrets: link_key: { env: LINK_KEY } # never the value
Backed up while it runs.
Litestream copies the database to the bucket without a pause. Documents and images go to the bucket too.
- All the timeLitestream copies each change of the database to the bucket.
- At start on a new hostThe engine restores the store from the bucket.
- Every weekA restore drill proves that the copy works.
- Before a deployA check of the outside services the store uses.
- After a deploy
check-deploy, and/healthzfor uptime monitors.
The limits of one engine.
A load test with k6 on one engine with 8 cores, at the volume of a large store. A load passes while 95 of 100 requests finish in under 500 ms.
| Load | Result |
|---|---|
| Home page alone | No limit at 135 a second; p95 3.6 ms |
| A category page alone | No limit at 11 a second; p95 6 ms |
| Buyers alone: add, cart, checkout, confirm, pay, order page | No limit at 54 buyers a second (324 requests a second); p95 4.6 to 8.5 ms; 5,489 orders paid in 3 minutes |
A mix of shop and back office (5 % /admin, 2 % buyers) | 91 a second at p95 231 ms; passes 500 ms at 114 a second; no buyer shed |
/admin/orders alone | Fails at 12 a second today: a fix is planned |
| Mailing to 160,000 contacts | Ready in 18 s; sent at about 130 a second, flat, in about 21 minutes |
| During the mailing | Cart writes p50 7 to 8 ms; sign-in mail p50 0.2 s, p95 0.5 s |
| Engine memory at the end | 500 MiB |
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. Source: the engine’s performance report of October 2026, parts 9 and 9b.
How a store grows.
The limit is the CPU that renders pages, not the database: the single writer was never near its limit, and reads run in parallel. So the path is in this order.
- Today
A CDN in front
Public pages are sent with cache headers. By calculation, not a test: with 9 of 10 public pages kept at the edge, a sale at 50 times normal traffic sends the engine 10 to 25 requests a second, 4 times or more under the measured plateau.
- Today
A larger server
A restart of minutes on most hosts. More cores help, but less than their count: 4 times the cores gave 1.8 to 2.3 times the pages in an earlier test.
- Planned
Faster back office pages
Paging for the
/admincatalogue and lighter order and home screens. Planned engine work of days. - Future project
Several engines for one store
Read-only engines on a copy of the database, behind a load balancer, for the public pages, with shared rate limits and shared images. Today one engine runs one store; this change is a future project, not yet scheduled.
- Only if needed
Another database
Postgres through the engine’s repository port, only if one server cannot take the writes. Nothing measured is near that.
Calm when it is busy.
Admission control
Under load the engine limits how much work it takes in at once.
Graceful restarts
A stop drains the requests in flight before the engine ends.
Cache headers
gzip, and cache headers for pages that are the same for every visitor. Edge cache purge on catalogue changes is a store setting.
The rules of this shape.
One engine runs one shop on one data folder. That is what keeps it simple, and it has rules.
Never run two engines on one data folder or one backup prefix.
No network file system for the data folder.
No autoscaling and no rolling deploys.
Never copy engine.db while the engine runs. For a copy, use the restore.
Source: docs/INTEGRATING.md and the deployment guide on main, 21 October 2026.