Scale & Low-Cost
Two questions answered together: how a parcel stays drastically cheaper to move than Porter or Bluedart, and how the tech behind it scales to millions of users without the cloud bill exploding.
1. Overview β two cost surfaces
"Cheap" at RideChain is not one number β it is two separate cost surfaces, each engineered down on purpose. Confusing them is the most common mistake, so we keep them apart throughout this page.
(a) Delivery cost
The unit economics of physically moving a parcel β partner payout, Point handling, hub consolidation, fuel and failed attempts. This is what the booker pays and what decides whether RideChain beats Porter/Bluedart on a 15 km interior run.
(b) Platform / infra cost
The cost of running the technology for millions of users β edge, compute, database, cache, storage, messaging. This decides whether the company stays solvent as MAU grows from thousands to millions.
flowchart TB ROOT["RideChain 'low cost'"] --> DEL["π¦ Delivery cost
(per parcel moved)"] ROOT --> INF["π₯οΈ Platform / infra cost
(per user served)"] DEL --> D1["Marginal / piggyback trips"] DEL --> D2["PUDO kills failed attempts"] DEL --> D3["Bundling Γ· N parcels"] DEL --> D4["Backhaul fills empty returns"] INF --> I1["Edge absorbs load (Cloudflare)"] INF --> I2["Geo-sharded PostGIS"] INF --> I3["Go = cheap per request"] INF --> I4["Async queues + caching"] classDef del fill:#e7f4ec,stroke:#1b7f4b,color:#115c36; classDef inf fill:#e8f0fb,stroke:#1f5fae,color:#143d6e; class DEL,D1,D2,D3,D4 del; class INF,I1,I2,I3,I4 inf;
2. Delivery cost thesis β the formula
The cost of moving one parcel is not "fuel for the distance". It is a small formula, and every term in it is a lever RideChain pulls in a direction incumbents structurally cannot:
flowchart LR TRIP["Trip cost
(fuel + partner time)"] --> NUM["(trip_cost β backhaul_revenue)"] BH["Backhaul revenue
(produce β mandi)"] --> NUM NUM --> DIV{"Γ· parcels_per_trip
(bundling ratio N)"} DIV --> FAIL["Γ (1 + failed_attempt_rate)"] FAIL --> ADD["+ fixed_overhead
(fleet, hubs, idle pay)"] ADD --> OUT["β cost per parcel"] classDef good fill:#e7f4ec,stroke:#1b7f4b,color:#115c36; class NUM,DIV,FAIL good;
cost/parcel β (trip_cost β backhaul_revenue) Γ· parcels_per_trip Γ (1 + failed_attempt_rate) + fixed_overhead. RideChain attacks every term: it lowers trip_cost (marginal trips), raises backhaul_revenue, raises parcels_per_trip, drives failed_attempt_rate toward zero, and zeroes fixed_overhead by owning no fleet or hubs.Read against the formula, the incumbents are expensive by construction:
| Term | Porter (on-demand truck) | Bluedart (parcel courier) | RideChain |
|---|---|---|---|
parcels_per_trip | β 1 β a dedicated vehicle per job | High in trunk, but β 1 on the rural last mile (low density) | 1.5 β 5+ on bundled milk-runs |
trip_cost | Full dedicated trip + driver idle pay between jobs | Loaded with hub sortation + line-haul | Marginal cost on a trip the partner was already making |
backhaul_revenue | β 0 β empty return paid by you | β 0 on rural spurs | > 0 β produce-to-mandi fills the empty return leg |
failed_attempt_rate | Low (on-demand, sender present) | High β rural re-attempts, address gaps | β 0 β parcel rests at a PUDO Point |
fixed_overhead | Vehicle financing, driver retainers | Owned hubs + fleet amortised over thin rural volume | β 0 β partners own vehicles, kiranas are the hubs |
3. The six structural cost levers
Six levers move the formula. Each is structural β built into how the network operates, not a temporary discount that has to be subsidised. Together they are the moat.
1 Β· Piggyback / marginal trip
A parcel rides a trip the partner was already making, so its true cost is only the marginal detour β not a whole dedicated trip. Porter literally cannot do this (it sells the dedicated trip). Saves: most of trip_cost.
2 Β· PUDO Points kill failed deliveries
The parcel rests at a RideChain Point (kirana / CSC / panchayat / chai stall); the receiver collects when convenient β ~100% first-attempt success, no costly re-attempt loops. Saves: the Γ(1+failed_attempt_rate) penalty.
3 Β· Bundling / VRP
The VRP batcher packs many parcels into one milk-run, so the trip cost is divided across N. Saves: cost Γ· N β the single biggest term mover.
4 Β· Backhaul
The empty return leg is sold: produce to the mandi, restock to a shop. backhaul_revenue goes from zero to positive, reducing net trip cost. Saves: subtracts revenue from the numerator.
5 Β· Zero owned fleet / hubs
Partners own the vehicles; kiranas are the hubs. There is no fleet to finance, no warehouse to amortise. Saves: drives fixed_overhead β 0.
6 Β· No stay-online subsidy
Partners are not paid to idle waiting for jobs β their opportunity cost is β 0 because they were travelling anyway. No "stay online" bonus burns capital. Saves: subsidy-per-delivery β 0.
4. Delivery cost comparison vs incumbents
The same 15 km interior parcel, priced four ways. These bands are canonical across the docs (see Commission & Pricing).
| Option | Price (15 km interior) | Speed | Why that price |
|---|---|---|---|
| Porter | βΉ150β250 | On-demand | Dedicated vehicle + driver, β 1 parcel, idle pay, empty return β every formula term is against it. |
| Bluedart | βΉ60β120 | 3β7 d (often fails) | Hub + fleet overhead amortised over thin rural density; repeated failed home re-attempts. |
| RideChain β urgent | βΉ70β90 | On-demand / same-day | Dedicated partner leg (no bundling), but still zero owned fleet/hub and no idle subsidy β so it lands below Porter. |
| RideChain β bundled milk-run | βΉ25β45 | Hours β next day | Marginal trip, PUDO (no failed attempt), cost Γ· N, often a backhaul. All six levers stacked. |
The milk-run band is reached by dividing the trip across parcels. Watch the cost-per-parcel collapse as the bundling ratio N climbs:
flowchart LR T["One milk-run trip cost
(say ~βΉ150 of marginal cost)"] --> N1["N = 1
β ~βΉ150/parcel"] T --> N3["N = 3
β ~βΉ50/parcel"] T --> N5["N = 5
β ~βΉ30/parcel β band"] T --> N8["N = 8
β ~βΉ19/parcel"] classDef hit fill:#e7f4ec,stroke:#1b7f4b,color:#115c36; class N5 hit;
N β 5 parcels lands squarely in the βΉ25β45 band. The numbers are illustrative; the shape (cost Γ· N) is the point.5. Delivery cost KPIs to instrument
Each lever maps to a metric we watch in production. If these drift, delivery cost drifts β so they are first-class dashboards, not vanity numbers.
| KPI | What it measures | Target | Tied to lever |
|---|---|---|---|
Parcels per trip (bundling ratio N) | Avg parcels carried on one milk-run | > 1.5 β 5+ | Bundling (Γ· N) |
| First-attempt success % | Deliveries completed without a re-attempt | β 100% (PUDO) | PUDO Points |
| Backhaul utilisation % | Return legs carrying paid load | Rising; the higher the better | Backhaul |
| % volume on cheapest tier | Share of parcels on bundled milk-run | Majority of non-urgent volume | Marginal / piggyback |
| Cost-per-delivery vs incumbent | RideChain βΉ/parcel Γ· Porter or Bluedart βΉ/parcel | Decisively < 1 | All six combined |
| Subsidy-per-delivery | Platform money burned per parcel to make it happen | β 0 | No stay-online subsidy |
6. Scaling to millions β the infra architecture
Now the second surface. The goal is to serve millions of users where the cost curve bends down per user, not up. The architecture is built so most traffic dies at the edge, the origin stays a cheap Go binary, and the only genuinely-scaling cost β the database β is tamed by geography.
flowchart TB
subgraph Clients["Millions of clients"]
APPS["π± Flutter apps + Next.js PWA
(offline-first)"]
end
subgraph Edge["Cloudflare edge (absorbs load first)"]
CFW["Workers
static Β· cache Β· rate-limit Β· auth precheck"]
R2["R2 object store
POD / KYC β no egress fee"]
end
subgraph Origin["Go modular monolith (cheap per request)"]
API["Stateless API / BFF
(horizontal scale)"]
HOT["Hot services peeled out:
matching Β· geo"]
end
subgraph DataT["Data tier"]
PGP["π PostgreSQL + PostGIS
primary, geo-sharded by region/block"]
RR["π Read replicas"]
REDIS["β‘ Redis
hot/live state, per region"]
Q["π¨ Queue
notifications Β· reconciliation"]
end
APPS --> CFW
CFW -. "cache miss / dynamic only" .-> API
CFW --- R2
API --> HOT
API --> PGP
API --> RR
API --> REDIS
API --> Q
PGP --> RR
classDef e fill:#fff3e0,stroke:#f4920b,color:#8a5200;
classDef c fill:#e7f4ec,stroke:#1b7f4b,color:#115c36;
classDef d fill:#e8f0fb,stroke:#1f5fae,color:#143d6e;
class CFW,R2 e; class API,HOT c; class PGP,RR,REDIS,Q d;
7. Scaling patterns
The architecture leans on a small set of well-worn patterns. The decisive one for RideChain is that the marketplace is naturally partitionable by geography β a parcel in one block almost never interacts with another block β so geography is a free, natural shard key and scale is near-linear.
| Pattern | How RideChain uses it | What it buys |
|---|---|---|
| Stateless API, horizontal scale | No session state in the API; add identical Go instances behind the edge | Add boxes = add capacity, linearly |
| Geo-sharding | Shard PostGIS by region / block β the natural shard key; each block is independent | Near-linear scale; a hot block touches only its shard |
| Read replicas | Reads (tracking, listings, ETAs) hit replicas; writes go to the primary | Offloads the read-heavy majority from the primary |
| Redis geo, per region | Live partner GPS, ETAs, surge, dispatch queues in a regional Redis | Hot-path reads never hit Postgres |
| Caching hot routes / ETAs | Common OSRM routes and ETAs cached at edge + Redis | Skips recompute for repeat geometry |
| CDN / edge offload | Static, tiles, assets, idempotent reads served from Workers / R2 | Most requests never reach origin |
| Async webhooks / reconciliation | Notifications, settlement reconciliation, payouts run off a queue | Spikes are buffered, not dropped |
| Backpressure | Rate-limit at edge; bounded queues shed / defer non-urgent work | Degrade gracefully instead of falling over |
flowchart LR
USERS["Users across India"] --> SK{"Shard key = region / block"}
SK --> B1["Block A shard
PostGIS + Redis"]
SK --> B2["Block B shard
PostGIS + Redis"]
SK --> B3["Block C shard
PostGIS + Redis"]
SK --> BN["Block N shard
add as you grow"]
classDef sh fill:#e8f0fb,stroke:#1f5fae,color:#143d6e;
class B1,B2,B3,BN sh;
8. Infra cost model β cost to millions
An illustrative budget for where the money goes as MAU grows. The numbers are deliberately rough β the shape is what matters: most lines are flat or sub-linear, and the database is the one line that genuinely scales (and is the one we work hardest to flatten).
| Cost line | How it scales with MAU | Why it stays low |
|---|---|---|
| Edge (Cloudflare Workers / CDN / WAF) | Cheap & near-flat | Absorbs most requests; predictable request-priced edge |
| Object storage (R2) | Grows with stored bytes, not users | No egress fee β serving POD/KYC reads is free |
| Compute (Go origin) | Scales with active jobs, not registered users | An idle MAU costs β nothing; Go packs dense per box |
| Database (PostGIS) | The main cost β scales with write/query load | Mitigated by sharding + read replicas + Redis/edge caching |
| Cache (Redis) | Scales with hot working-set, per region | Sized to live state only; not a system of record |
| Messaging (SMS / IVR / WhatsApp / FCM) | Per-message, scales with sends | FCM push is ~free; SMS reserved for fallback |
Contrast the two budget shapes:
flowchart TB
subgraph Naive["β Naive 'always-on cloud' bill"]
NA["Per-user always-on servers"] --> NB["Cost climbs ~linearly
with REGISTERED users"]
NB --> NC["Idle users still burn compute
β bill explodes at millions"]
end
subgraph RC["β
RideChain shape"]
RA["Edge absorbs + R2 no-egress"] --> RB["Compute scales with ACTIVE jobs"]
RB --> RD["DB sharded by geography"]
RD --> RE["Cost curve bends sub-linear per MAU"]
end
classDef bad fill:#fdecea,stroke:#c0392b,color:#7d211a;
classDef good fill:#e7f4ec,stroke:#1b7f4b,color:#115c36;
class NA,NB,NC bad; class RA,RB,RD,RE good;
9. Reliability at scale β cheap AND dependable
Low cost must not buy fragility. The same choices that keep the bill low also keep the system up: there is no expensive always-on redundancy, just patterns that degrade gracefully instead of failing hard.
Graceful degradation
Offline-first apps queue actions in a local outbox; the queue + retry buffers spikes; the payment gateway falls back (Razorpay β Cashfree) on live success-rate. A degraded leg still completes later, it does not drop.
No single point of failure
Stateless API instances are interchangeable; read replicas survive a primary blip for reads; per-region Redis isolates blast radius; the edge keeps serving cached/static even if origin is busy.
Idempotency everywhere
Every external call (PG, SMS, KYC) and every booking action carries an idempotency key, so retries, replays and re-delivered webhooks never double-charge or double-book.
Append-only money
The escrow ledger is append-only; balances are projections. Reconciliation and audit stay deterministic even under partial failure β see Split-Money Settlement.
10. Edge cases & failure modes
Scale and cost optimisations create their own failure modes β a shard gets hot, a queue stampedes, the bill runs away. Each has a defined mitigation; the full catalogue is in the Edge-Case Catalog.
| Scenario | Mitigation |
|---|---|
| Hot region / block overloads one shard | Detect skew; split / re-shard the block; route reads to replicas; cap that shard's heavy work. |
| Thundering herd on surge / festival open | Rate-limit at the Cloudflare edge; queue dispatch; serve cached quotes; shed non-urgent work first. |
| DB write hotspot on the money ledger | Append-only writes partitioned by month + region; batch + queue settlement writes off the hot path. |
| Redis eviction loses live state | Treat Redis as a cache, not a source of truth; rebuild from Postgres; tune TTLs and maxmemory policy. |
| OSRM CPU spike on a big VRP | Cap stops per run, time-box the solve, fall back to a greedy route; cache hot route geometry. |
| Webhook storm (PG / KYC re-deliveries) | Idempotency keys + a bounded queue absorb duplicates; reconciliation job is the backstop. |
| Cache stampede on an expired hot key | Per-key lock (single-flight) + stale-while-revalidate so only one rebuild runs while others serve stale. |
| Cross-region latency for a far user | Edge terminates close to the user; reads hit the nearest regional DB / replica; keep writes within the shard. |
| Cost runaway (autoscale gone wild) | Budgets + billing alerts; hard autoscale caps; backpressure sheds load before the bill spikes. |
| Cold-start a brand-new region | Seed Points + partners first, then open bookings; a region with no supply never accepts demand it can't serve. |
| Festival 10Γ spike | Surge prices demand down; edge absorbs read load; async queues defer non-urgent work; shards scale per region. |
| Low-connectivity clients drop mid-action | Offline outbox persists the action and replays on reconnect, deduped by idempotency key. |