A structured UI prototype for CRUD applications with complex business processes, demonstrating a cohesive e-commerce order fulfillment workflow using modern technologies.
- Frontend: HTML/CSS/JavaScript + datastar.dev (SSE-based hypermedia)
- Backend: Chi router + Restate Go SDK + pithomlabs/rea framework
- Database: SQLite (modernc.org/sqlite - pure Go)
- Patterns: Virtual Objects, Sagas, Awakeables, Durable Promises
prototype/
├── backend/
│ ├── main.go # Server entry point
│ ├── go.mod # Dependencies
│ ├── db/
│ │ ├── sqlite.go # SQLite initialization
│ │ └── migrations/
│ │ ├── 001_init.sql # Schema
│ │ └── 002_seed.sql # Sample data
│ ├── models/
│ │ └── models.go # Data models (SQLite + Restate)
│ ├── services/
│ │ ├── shipping_service.go # Stateless service with rea.RunWithRetry
│ │ ├── user_session.go # Virtual object (cart + checkout)
│ │ └── order_workflow.go # Saga workflow with compensations
│ └── handlers/
│ ├── auth.go # Auth middleware
│ ├── ingress.go # Restate ingress handlers (IN PROGRESS)
│ ├── products.go # SQLite product queries (TODO)
│ └── static.go # Frontend file serving (TODO)
├── frontend/ # (TODO)
│ ├── index.html
│ ├── admin.html
│ ├── css/
│ └── js/
├── data/ # SQLite database location
│ └── app.db # Created on first run
├── PROPOSAL.md # Original proposal
├── PROPOSAL2.md # Updated proposal with SQLite
└── README.md # This file
- SQLite schema (products, users, shipping_zones, notifications, order_history)
- Database initialization with modernc.org/sqlite
- Data models for all entities
- ShippingService (Restate Service)
InitiateShipment()with rea.RunWithRetryCancelShipment()compensation handler
- UserSession (Restate Virtual Object)
AddItem()- add product to cartGetBasket()- view cart itemsCheckout()- initiate checkout with payment Awakeable + state-based idempotency (Pattern C)
- OrderFulfillmentWorkflow (Restate Workflow)
Run()- main saga orchestration with defer compensationsOnApprove()- resolve admin approval promise
- Main server with Chi router
- Auth middleware (X-User-ID header extraction)
- Ingress handlers (cart, checkout, payment callback, workflow approval)
- [ ] Product catalog handlers (SQLite queries)
- SSE streaming endpoints
- Static file serving
- Frontend HTML/CSS/JS with datastar.dev
- Admin UI (separate portal)
- Notification system with SQLite persistence
- Order history tracking
- Complete testing scenarios
- Go 1.23+
- Docker (for Restate runtime)
For a quick taste of Restate server, download it to your local device here
For testing/QA, I recommend using Docker which you can download here. Save the trouble of installing Docker by downloading the deb binaries based on your Linux distro.
docker run --name restate_dev --rm \
-p 8082:8082 -p 9070:9070 -p 9071:9071 \
--add-host=host.docker.internal:host-gateway \
docker.io/restatedev/restate:latestFor this repo, run the convenience script
./register-services.shhttp://localhost:9070/I recommend using LiteIDE for easy one-click compile of golang programs. Download v38.3 here
cd backend
go mod tidy
go build -o server .
./serverThe backend will:
- Initialize SQLite database at
./data/app.db - Run migrations and seed sample data
- Start Restate SDK server on
:9080 - Start HTTP server on
:8082
- Frontend: http://localhost:8082
- Admin UI: http://localhost:8082/admin
- Health Check: http://localhost:8082/health
1. Browse Products (SQLite query)
↓
2. Add to Cart (UserSession.AddItem - Restate state)
↓
3. Checkout (UserSession.Checkout)
├─ Create Payment Awakeable
├─ [SUSPEND] Wait for payment...
└─ [RESUME] on payment callback
↓
4. Launch Workflow (OrderFulfillmentWorkflow.Run)
├─ [SUSPEND] Wait for admin approval (Durable Promise)
├─ [RESUME] on admin approval
├─ Call ShippingService.InitiateShipment (Durable RPC with retry)
├─ Durable Sleep (5 seconds for delivery)
└─ Complete
On Failure:
└─ Trigger Compensations (LIFO order)
├─ CancelShipment (if shipping succeeded)
└─ Release Inventory
GET /api/products- List all productsGET /api/products/{id}- Get product details
POST /api/cart/add- Add item to cart- Header:
X-User-ID: alice - Body:
{"product_id": 1, "quantity": 2}
- Header:
GET /api/cart- View cart- Header:
X-User-ID: alice
- Header:
POST /api/checkout- Initiate checkout- Header:
X-User-ID: alice - Body:
{"order_id": "order-123", "shipping_address": "..."} - Response: Payment awaitable created, returns awaitable ID
- Header:
POST /api/payment/callback- External payment gateway webhook- Body:
{"awakeable_id": "...", "transaction_id": "txn-456", "amount": 10000, "status": "success"} - Resumes suspended checkout
- Body:
POST /api/workflow/{orderID}/approve- Admin approves order- Body:
{"approved": true}
- Body:
GET /api/workflow/{orderID}/status- Get workflow state
GET /stream/notifications- Real-time notification streamGET /stream/workflow/{orderID}- Workflow progress updates
# Add item to cart
curl -X POST http://localhost:8082/api/cart/add \
-H "X-User-ID: alice" \
-H "Content-Type: application/json" \
-d '{"product_id": 1, "quantity": 2}'
# Checkout (creates payment awakeable)
curl -X POST http://localhost:8082/api/checkout \
-H "X-User-ID: alice" \
-H "Content-Type: application/json" \
-d '{"order_id": "order-123", "shipping_address": "123 Main St"}'
# Simulate payment success (resolve awakeable)
curl -X POST http://localhost:8082/api/payment/callback \
-H "Content-Type: application/json" \
-d '{"awakeable_id": "<ID_FROM_LOGS>", "transaction_id": "txn-456", "amount": 10000, "status": "success"}'
# Admin approves workflow
curl -X POST http://localhost:8082/api/workflow/order-123/approve \
-H "Content-Type: application/json" \
-d '{"approved": true}'
# Result: Order completes after 5-second delivery timer# Simulate payment rejection
curl -X POST http://localhost:8082/api/payment/callback \
-d '{"awakeable_id": "<ID>", "status": "failed"}'
# Result: Checkout fails, workflow NOT launched, cart preserved# Admin rejects order
curl -X POST http://localhost:8082/api/workflow/order-123/approve \
-d '{"approved": false}'
# Result: Workflow triggers compensations, inventory released# Use special order ID that triggers shipping failure
curl -X POST http://localhost:8082/api/checkout \
-H "X-User-ID: alice" \
-d '{"order_id": "FAIL_SHIP", ...}'
# Result: ShippingService fails, compensations triggered- UserSession.Checkout creates Awakeable
- Payment gateway receives awakeable ID
- External callback resolves Awakeable
- Checkout resumes automatically
- Defer-based compensation stack (LIFO)
- Guarded compensations (only if step succeeded)
- TerminalError triggers rollback
- Workflow suspends waiting for promise
- Shared handler resolves promise
- Workflow resumes automatically
- Explicit deduplication keys in Restate state
- Early return if already executed
- Prevents duplicate payments/workflows
- PROPOSAL2.md - Detailed architecture proposal
- rea-06-sonnet45 - Reference implementation
- Restate Documentation
- rea Framework
- datastar.dev
Prototype/Educational Project
