Live location at scale
GPS updates flow through Kafka, not your main database. Hundreds a second never slow your shop down.
Open source · Self-hosted · Built in Tokyo
Your business already takes orders. Tasuki adds the delivery side: your system sends an order over the API, Tasuki finds the nearest driver, streams the driver's position to your customer's phone, and reports every status change back to you.
Early and honest: orders, live tracking and the fleet pipeline run today; dispatch is being finished. See exactly what's built.
Why it exists
When customers start asking for delivery, you need a second system. It must track every moving driver every few seconds, assign the right one in under a minute, never lose or double-book an order, and keep each customer's map live. That is a different kind of software from a shop or an ordering app, and it should not share a server with one. Tasuki is that system, ready to deploy next to yours.
GPS updates flow through Kafka, not your main database. Hundreds a second never slow your shop down.
Idempotency keys, a transactional outbox and deduplicated events make every retry safe.
A signed tracking link per order, live in any phone browser. Nothing to install. English and Japanese.
Your cloud, your region, your data. No per-delivery fee to a vendor and no lock-in. MIT licensed.
Who it's for
Restaurant groups, grocers, pharmacies, retailers. Your checkout calls the API; your drivers get offers on their phones; your customers get a live link.
Serve many merchants from one installation. Every merchant is a tenant with its own API keys and stores, and every query is scoped to its tenant.
Rather not spend a year building dispatch and tracking? Start from a documented, tested design and change what your business needs.
How it works
A 襷 (tasuki) is the sash that ekiden relay runners hand to each other. Tasuki hands every order on the same way: your system, then dispatch, then a driver, then your customer. The platform's job is to make sure the sash is never dropped, never handed to two runners, and always visible.
Ask for a price and an ETA, then create the order with an Idempotency-Key. You get an order
ID and a tracking link for your customer.
POST /v1/quotes · POST /v1/orders
The nearest free driver gets an offer with a 30-second timer. On a decline or a timeout, the next one does. Travel times come from real roads (OSRM).
offers over server-sent events
The driver's phone sends GPS in small batches. Your customer's tracking page moves the marker live and keeps the ETA honest.
POST /v1/locations · GET /v1/track/…/stream
Every change (confirmed, assigned, picked up, delivered) is an event with a full history. Signed webhooks that push it to you are next on the roadmap.
GET /v1/orders/{id} · webhooks (next)
Integrate
Keep your shop, your app and your database. Tasuki sits beside them and talks plain JSON over HTTPS. These
are the real endpoints: run make up and they answer on your laptop.
# Locally (make up): ORDERS=http://localhost:8000
# 1. Ask for a price and an ETA. A quote is valid for 2 minutes.
curl "$ORDERS/v1/quotes" \
-H "Authorization: Bearer $TASUKI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"store_id": "str_01JA2Q…",
"dropoff": {
"lat": 35.6618, "lng": 139.6983, "ward": "shibuya",
"address": "1-2-3 Jinnan, Shibuya-ku",
"customer_name": "Sato Hana", "customer_phone": "090-1234-5678"
}
}'
# 201 {"quote_id": "quo_01JA2R…", "fee_yen": 742, "eta_seconds": 1920, "expires_at": "…"}
# 2. Turn the quote into an order. Retrying with the same key never creates a second one.
curl "$ORDERS/v1/orders" \
-H "Authorization: Bearer $TASUKI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: checkout-8812" \
-d '{"quote_id": "quo_01JA2R…"}'
# 201 {"order_id": "ord_01JA2S…", "status": "confirmed", "tracking_url": "…/track/eyJhbGci…"}
// Send your customer the tracking_url as it is (a hosted page in English and Japanese),
// or draw the delivery inside your own app. Locally: TRACKING = "http://localhost:8083".
const stream = new EventSource(`${TRACKING}/v1/track/${token}/stream`);
stream.addEventListener("status", (e) => {
const { status, eta } = JSON.parse(e.data); // confirmed → assigned → picked_up → delivered
renderStatus(status, eta);
});
stream.addEventListener("position", (e) => {
const { lat, lng } = JSON.parse(e.data); // the assigned driver, every few seconds
moveDriverMarker(lat, lng);
});
// delivered, cancelled, failed or expired: the server closes the stream
stream.addEventListener("end", () => stream.close());
# What a driver app sends. Locally: FLEET=http://localhost:8081, DISPATCH=http://localhost:8082
# Every few seconds while moving: a batch of 1 to 50 GPS points.
curl "$FLEET/v1/locations" \
-H "Authorization: Bearer $DRIVER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"points": [{
"lat": 35.6581, "lng": 139.7017, "accuracy_m": 8,
"speed_mps": 4.2, "heading_deg": 90,
"device_time": "2026-10-16T03:12:08Z",
"status": "to_dropoff", "order_id": "ord_01JA2S…"
}]}'
# 202 {"accepted": 1, "dropped": 0} (503 + Retry-After when the platform sheds load)
# Offers arrive on a stream. The driver has 30 seconds to answer.
curl -N "$DISPATCH/v1/couriers/me/offers/stream" -H "Authorization: Bearer $DRIVER_TOKEN"
curl -X POST "$DISPATCH/v1/offers/off_01JA2T…/accept" -H "Authorization: Bearer $DRIVER_TOKEN"
# Proof of delivery: the driver must be within 500 m of the drop-off.
curl -X POST "$ORDERS/v1/courier/orders/ord_01JA2S…/deliver" \
-H "Authorization: Bearer $DRIVER_TOKEN" -H "Content-Type: application/json" \
-d '{"lat": 35.6619, "lng": 139.6981}'
# Today: read an order with its full status history.
curl "$ORDERS/v1/orders/ord_01JA2S…" -H "Authorization: Bearer $TASUKI_API_KEY"
# Next on the roadmap: signed webhooks to your endpoint, retried until it answers 2xx,
# signed with HMAC-SHA256 over a timestamp and the body, with a 5-minute replay window.
# They carry the events the platform already publishes inside, for example:
{
"schema": "order.event.v1",
"event_id": "evt_01JA2V…",
"type": "OrderPickedUp",
"order_id": "ord_01JA2S…",
"merchant_id": "mer_01JA2P…",
"occurred_at": "2026-10-16T03:14:41Z"
}
Full reference: OpenAPI spec · every endpoint, event and stream. IDs and tokens above are shortened.
What's inside
Nothing on this page is marked as working unless it is written, tested and in the repository.
Quotes, idempotent orders, cancellation and status history. Django and PostgreSQL, tested against real database races.
Order changes and their events commit together, then reach Kafka in order. No lost events, no phantom ones.
Authenticated GPS batches from drivers. Under overload it answers 503 with Retry-After instead of falling over.
The latest position of every driver in Valkey, geo-indexed for nearest-driver queries, rebuilt from Kafka after a loss.
Server-sent event streams for one order (customers) or the whole fleet (operators), with a hosted page in English and Japanese.
OSRM on real OpenStreetMap roads for travel times and routes, with a straight-line fallback if it is down.
Merchants, customers and drivers through the public APIs, with repeatable scenarios such as a rainy Friday lunch.
Five SLOs with burn-rate alerts, a runbook per alert, Grafana dashboards in git, and a gate that blocks risky releases.
Nearest-driver offers with timeouts and ETAs for quotes. Greedy first; batched matching comes later.
Terraform for AWS (VPC, EKS, Karpenter) and GitOps with Argo CD: written and checked, first cluster run next.
Every order event pushed to your endpoint, signed, retried, with a dead-letter queue and replay.
Orders, drivers and the live map behind a login. Manual assignment, API keys and webhook settings.
Offers, navigation, pickup and proof of delivery on the driver's phone, using the same public API.
Service zones from GeoJSON, any OpenStreetMap region, any currency and tax rule. Today the service area is Tokyo.
Ask "why is this order late?" and get an answer built from read-only tools over orders, dispatch and the fleet.
Bookable windows (時間帯指定) without overbooking, a double-entry ledger, and weekly driver payouts.
Architecture
Orders are few and precious. Locations are many and disposable. Tasuki keeps the two apart, so a flood of GPS points can never stop an order, and the order path never trades correctness for speed.
| Orders and money | Locations and tracking | |
|---|---|---|
| Volume at peak | Single-digit writes a second, even in a surge | About 750 GPS updates a second |
| "Correct" means | Exactly-once effects: never lost, never charged twice | Latest wins: a missed point is harmless if the next one arrives |
| Source of truth | PostgreSQL, with a transactional outbox | The Kafka log; Valkey is a cache rebuilt from it |
| On failure | Reject or queue, never guess | Serve the last known position and say how old it is |
| Language | Python and Django: rich domain model, transactions | Go: high throughput, small memory, cheap concurrency |
event_id.
Read the full system design.
Tracking only flows one way, from the platform to the screen. Server-sent events run over plain HTTP, pass through proxies and load balancers without special setup, and reconnect on their own. Drivers send GPS the other way as small batched HTTPS requests, which survive flaky mobile networks better than a long-lived socket.
Scale
Every design choice has a number behind it. These are the targets for a busy city operator, with room for a rainy Friday, when demand triples and every customer is watching the map.
These are design targets, not measurements yet. The simulator already has a design-scale rainy-Friday scenario. Load-test results will be published here with the scripts to reproduce them, and not before.
At three times normal demand, orders want 18,000 deliveries an hour while drivers can do about 7,200. The servers cope easily; what breaks is the promise. So in a surge Tasuki quotes honestly: longer ETAs, fewer bookable windows, a surge fee. And it stays up.
Every service is stateless and scales horizontally behind Kubernetes. Kafka is keyed by driver and by order, so each one's events stay in order while consumers spread across partitions. Karpenter adds spot nodes when load rises and removes them after.
When things break
Every part fails eventually. Each failure below has a planned response, and each one becomes a game-day experiment with a written postmortem.
| Failure | What your customers see | What Tasuki does |
|---|---|---|
| Valkey (cache) lost | Nothing on orders or tracking; new assignments pause for seconds | Tracking reads Kafka, not the cache. fleet-state replays recent locations to rebuild it; dispatch waits for the rebuild. |
| Kafka unavailable | Orders still accepted; status updates late | Outbox rows wait in PostgreSQL and drain later. Ingest sheds load with Retry-After. |
| Database failover | Order creation fails for 1 to 2 minutes | Clients get 503 with Retry-After. Idempotency keys make every retry safe. |
| Routing (OSRM) down | ETAs a little less exact | Dispatch falls back to straight-line distance with a detour factor, and widens quotes. |
| Rain surge (3× demand) | Longer ETAs, fewer windows, a surge fee | Quotes follow driver supply. Priority shedding: orders, then dispatch, then tracking, then history. |
| One availability zone lost | Brief retries | Pods spread over three zones with disruption budgets; Multi-AZ database; Kafka replication factor 3. |
Operate
Written objectives, alerts that point to a runbook, and releases that stop themselves when reliability slips.
| Promise | Target |
|---|---|
| Quote and order requests succeed | 99.9 % |
| Orders are created in under 300 ms | 95 % |
| GPS points reach live state within 2 s | 99 % |
| Customers see positions younger than 10 s | 99 % |
| A driver accepts within 60 s of confirmation | 95 % |
Deploy
Docker Compose runs PostgreSQL, Kafka, Valkey and every service, then the simulator fills the map.
cp .env.example .env
make up # every service, healthy
make sim-up # the city starts moving
open http://localhost:8088
A Helm chart per service and an Argo CD app of apps, with Kyverno policies, Strimzi Kafka, CloudNativePG with backups, and canary releases through Argo Rollouts.
Terraform for the VPC, EKS and Karpenter (spot first). About $8 a day while it runs, and
make aws-down takes it back to nearly zero.
Built in Tokyo
The reference deployment covers Tokyo's 23 wards on real Tokyo roads. Japanese delivery has its own rules, so they are built in from the start.
Roadmap
Released as semantic versions with a changelog. Follow along on GitHub.
Orders, fleet ingest, live tracking, routing, the simulator and the live map; finishing dispatch; the first cluster run on AWS; published load-test numbers; the first game day and postmortem.
Service zones, currency and tax for any city; signed webhooks; an operations dashboard; a driver app; and a single-server install for smaller teams.
An assistant that explains late orders and unusual patterns, using read-only tools over orders, dispatch and the fleet.
Batched dispatch, delivery windows, an order saga on Temporal, a double-entry ledger with daily reconciliation, and OAuth2 for partners.
Questions
Yes. Tasuki is MIT licensed: run it, change it and use it commercially. You pay only for the cloud resources you run it on.
Not yet. The service area, the zones and the pricing are Tokyo's for now. Making them configurable for any city is the first item on the "Next" list.
Not to try it: Docker Compose runs the whole stack on one machine. The production path today is Kubernetes. A single-server production install for smaller teams is on the roadmap.
In your own cloud account and the region you choose. Tasuki sends nothing anywhere else.
Not yet. The simulator plays every driver through the same public API a real app will use, so any app can integrate today. A driver app is on the "Next" list.
Tasuki is an open-source project, not a delivery company. The merchants, drivers and customers in the demo are generated by the simulator. The software, the infrastructure and the reliability work are real.
Tell me about your city, your daily order volume and the system you run today. I'd like to hear what Tasuki would need to run your deliveries.