Back to archive
IV. Client Builds & Logistics Platformsshowcaseleadclient anonymised

Arryt — Courier Logistics v1

A full courier-delivery management platform (for Restaurant chain (UZ)/Restaurant chain (UZ)): a Bun/Elysia backend with real-time order dispatch, BullMQ queues, OLAP analytics on DuckDB via CDC replication from Postgres over gRPC, an admin panel on Refine, and a Flutter courier mobile app.

Status
maintained
Period
2023-11-04 → 2025-03-09
AI sessions
Stack
Languages
TypeScriptDartSQL
Frameworks · Infra
Elysia (Bun)Apollo GraphQLDrizzle ORMBullMQDuckDBgRPCRefine + Ant DesignFlutter/BLoCOpenTelemetry
§01

Overview

  • What it is: monorepo for a food-delivery system. Accepts orders, dispatches them to couriers in real time (factoring in geolocation, queues, shifts, "daily garant"), integrates with Yandex Dostavka as a fallback service, calculates courier salaries/balances, ratings and reports. Seven sub-services: api (Elysia backend), queue (BullMQ workers), crons (scheduled tasks), duck_api (OLAP analytics on DuckDB), transfer_db (data migration), admin (Refine panel), mob (Flutter courier app).
  • Type / status / role: web-app (distributed system + mobile) · maintained (lived for ~1.5 years, actively) · lead — the user is co-lead with Ilhombek (≈78 vs 59 commits).
  • Activity window: 2023-11-04 → 2025-03-09. A long-lived production system with stack evolution inside: the Prisma→Drizzle migration and the NestJS-like layer→Elysia migration are visible in large "shake-up" commits (92 files +2962/−3418, 35 files +2386/−2924, 29 files +2002/−2341).
§02

Stack

  • Languages: TypeScript (backend/admin), Dart (Flutter mobile), SQL (Postgres + DuckDB).
  • Frameworks/libraries:
  • *Backend (api):* Bun + Elysia (clustered via node:cluster, 4 workers in prod), Apollo GraphQL (@elysiajs/apollo) + REST, Drizzle ORM (drizzle-typebox, drizzle-zod), Postgres (postgres/pg), BullMQ + Bull, ioredis, jose (JWT), bcrypt, geolib (geo math), dayjs (utc/timezone), lodash/radash, @evan/duckdb + gRPC client to duck_api.
  • *Analytics (duck_api):* DuckDB (duckdb-async) with a Postgres extension connection (ATTACH … TYPE POSTGRES), pg-logical-replication (CDC), Kafka (kafkajs + node-rdkafka), Hono + Elysia, gRPC server (arryt.proto, service Transactions).
  • *Admin:* Refine (@refinedev/antd, @refinedev/graphql, kbar) + Ant Design 5, TanStack Query, React 18, Vite, Yandex Maps (react-yandex-maps), Excel/PDF export, react-hook-form, i18next.
  • *Mobile (mob):* Flutter + flutter_bloc, auto_route, Dio + HTTP/2, Firebase (analytics/crashlytics/messaging/performance/remote_config), flutter_background_service (background courier GPS tracking), flutter_local_notifications, chatview (chat), inappwebview.
  • Infra/deploy: Bun runtime (bun.lockb in every package), PM2 (queue/pm2.config.js), clustered API. Redis for queues and cache. Observability: OpenTelemetry (@opentelemetry/sdk-node, OTLP exporter), Prometheus (prom-client), Pino + pino-loki (logs to Grafana Loki).
  • Data: Postgres (OLTP, primary DB via Drizzle), DuckDB (OLAP/analytics, separate service), Redis (queues + cache). gRPC as transport between api and duck_api.
  • Notable tooling: custom Bun plugin (proto.ts) for importing .proto directly as modules; a custom parseFilterFields/parseSelectFields layer for dynamic Drizzle queries from admin filters.
§03

What was shipped

NOTE: commit messages in this repo are mostly junk ("dddd", "dd", "ddd", "fff", "solved") — conclusions are drawn from code, not messages.

  • Stack migration: large commits with almost equal +/− (92 files +2962/−3418 and so on) — backend port to Bun/Elysia + Drizzle (in api there's still a prisma/ artifact and ~schema.gql, with @prisma/client alongside drizzle — a transition period).
  • Order dispatch: built a BullMQ-backed courier assignment engine (~18 queues/workers): new_order_notify, try_assign_courier, push_courier_to_queue, set_queue_last_courier, change_courier, clear_courier, order_complete, change_status, store_location (courier GPS), send_notification, order_index (search index), try_set_daily_garant.
  • Yandex Dostavka integration: workers check_and_send_yandex + yandex_callback — auto-handoff to an external service when an in-house courier isn't available.
  • OLAP analytics: service duck_api — mirrors Postgres tables into DuckDB + CDC via logical replication/Kafka, serves aggregates (withdraw/transaction reports) via gRPC.
  • Reports and calculations: crons/calculate_courier_performance.ts (monthly courier rating), balance_report_send.ts, send_courier_withdraws_report.ts; orders/controller.ts at 3054 lines — guarantee reports, delivery pricing, summaries.
  • Courier mobile app: Flutter with background GPS, push, chat, BLoC architecture.
  • Volume: 148 commits over ~16 months by two primary developers; the user is the largest contributor (~78 commits, counting his 3 identities).
§04

Technical challenges

All confirmed against files/diffs:

  • OLTP→OLAP via DuckDB + CDC (duck_api/src/sync_duck.ts, arryt.proto, api/src/lib/duck_grpc.ts): heavy analytical queries (courier transaction/withdraw history) moved out of Postgres into DuckDB. Sync uses the native DuckDB Postgres extension (INSTALL postgres; ATTACH '…' AS db (TYPE POSTGRES); CREATE TABLE … AS FROM db.<table>) + streaming delta via pg-logical-replication and Kafka. Results flow back to the main API over gRPC (Transactions.getWithdrawTransactions). → Demonstrates understanding of the OLTP/OLAP split, CDC, and inter-service gRPC — serious data-engineering work.
  • Real-time dispatch on queues (queue/index.ts + 16 processors): ~18 BullMQ Queue/Worker pairs over a single Redis, the courier-assignment pipeline with a "last courier per terminal" queue, fallback to Yandex, user cache refresh, search indexing. → Designing an event-driven system with workers separated by responsibility.
  • Courier ranking algorithm (crons/calculate_courier_performance.ts): resolves the "linked terminals" graph (getLinkedTerminalIds), batch-fetches all orders and groups via lodash, 3 concurrent queries through Promise.all (count / avg-score / list for ranking position), computes average delivery time and ranks couriers (sort by delivery count ↓, then by average time ↑). Per-courier try/catch with continue — partial failures don't bring the whole cron down. → Production robustness + non-trivial business logic.
  • Clustered Elysia with observability (api/src/index.ts, app.ts, package.json): in prod, 4 workers forked via node:cluster, OpenTelemetry + OTLP export, Prometheus metrics (prom-client), structured logs to Loki (pino-loki). → Mature operations posture.
  • Dynamic query layer (api/src/lib/parseFilterFields.ts, parseSelectFields.ts, with sql.placeholder for prepared statements): the admin panel (Refine) sends filters/field selections → the backend safely builds Drizzle queries. → A reusable abstraction instead of copy-paste in every controller.
  • Custom Bun plugin for .proto (proto.ts): Bun.plugin with an onLoad filter /\.proto$/, parses protobuf and returns a JS module (loader "object"). → Non-standard knowledge of Bun runtime tooling.
  • Heavy Flutter client (mob/pubspec.yaml): background GPS service (flutter_background_service + disable_battery_optimization), the full Firebase stack, HTTP/2 via Dio, BLoC, auto_route, embedded chat. → A real production mobile app for couriers, not a prototype.
§05

AI-assisted development

  • Sessions found: 0 in the local Claude Code sessions directory for this project. Sessions exist for the separate new_arryt project (and its mobile sub-directory) — that's a rewrite, covered in task #37, not this one.
  • What was done with AI: no data for this repo.
  • AI workflow patterns: none — the project was largely written before active Claude Code usage (2023–2025, before migrating to new_arryt).
§06

Achievements & metrics

  • Scale: monorepo of 7 sub-services, ~25 domain modules in api/src/modules/ (orders, couriers/users, terminals, delivery_pricing, daily_garant, order_transactions, manager_withdraw, brands, organizations, roles/permissions, work_schedules, chart, missed_orders, …).
  • Core complexity: orders/controller.ts — 3054 lines of business logic; ~18 background workers; api version 1.0.50.
  • Real load: production food delivery (Restaurant chain (UZ)/Restaurant chain (UZ)), Yandex Dostavka integration, courier salary/balance calculation — the system ran for ~1.5 years.
  • Completeness: backend + analytics + admin + mobile — closes the entire delivery loop.
§07

Contributors

git shortlog · all branches

  1. Dave9378
  2. i767175759
  3. root8
  4. shahzodsalimsakov2
  5. Macbook Pro1
5 contributors148 commits total
Currently

Open to Senior / Staff engineering roles and selective freelance — production AI, platform, and full-stack work.

Get in touch