Skip to content

πŸ›’ Product marketplace

Multi-tenant sales platform Mercado Livre / Shopee style, no external integrations. The point is to exercise tempest-fastapi-sdk in a realistic scenario β€” auth, multi-tenant, RBAC, idempotency, auditable stock, orders with a state machine, real-time SSE status, MinIO uploads, transactional email.

Project pages

Page What's there
Business rules The domain written as prose β€” who can do what, under which conditions. Read first.
Domain model UML class + ER diagrams, every entity explained (attributes, invariants, relationships).
Critical flows Sequence diagrams covering signup, member invite, product creation, checkout, shipment. Order and Invitation state machines.
Endpoint map Table of the whole REST API with method + path + auth + payload + status.

Project setup (5 min)

# 1. Scaffold via SDK
tempest new marketplace --extras auth,admin,upload,cache,email,minio,queue,tasks,metrics

# 2. Boot the infra
cd marketplace
docker compose up -d

# 3. Configure env
cp .env.example .env
uv sync

# 4. Migrations (create the schema, including the users table)
uv run tempest db revision -m "init"
uv run tempest db upgrade

# 5. Bootstrap the first admin so /admin login works
uv run tempest user create --email admin@local --password admin-pass-12 --admin

# 6. Run
uv run python main.py

When the service boots you have:

  • REST API at http://localhost:8000
  • Swagger docs at http://localhost:8000/docs
  • SDK admin panel at http://localhost:8000/admin
  • MinIO console at http://localhost:9001 (minioadmin/minioadmin)
  • RabbitMQ UI at http://localhost:15672 (guest/guest)
  • MailHog UI at http://localhost:8025

SDK stack exercised

Need SDK primitive
Public signup + login + password reset UserAuthService + make_auth_router (signup / activate / login / password-reset ready since v0.31.0) + BaseUserModel + BaseUserTokenModel
Access-token refresh via JWT pair JWTUtils + make_jwt_user_dependency
Multi-tenant membership BaseRepository[T], make_role_dependency, make_permission_dependency
Member invitation EmailUtils.render_template + generate_opaque_token/hash_opaque_token
Variants + versioned prices BaseModel + AuditMixin + SQLAlchemy 2.0 async relationships
Append-only stock with bulk seed BaseModel (movement) + BaseRepository.bulk_create_values / bulk_upsert (v0.28+)
Non-duplicating checkout IdempotencyMiddleware + RedisIdempotencyStore
Upload body-size limit BodySizeLimitMiddleware (v0.28+)
Product images UploadUtils + MinIOUploadStorage + presigned URLs
Real-time order status EventStream, sse_response
Async notifications AsyncTaskBrokerManager (TaskIQ) + AsyncBrokerManager (FastStream)
Public catalog cache AsyncRedisManager, @cached
Oncall metrics PrometheusMiddleware + make_prometheus_router (v0.28+) and MetricsUtils
Social OAuth (Google / GitHub) GoogleOAuthClient / GitHubOAuthClient / OIDCProvider (v0.29+)
Safe server-rendered forms CSRFMiddleware (v0.29+)
Outbound calls to external services HTTPClient (v0.28+) with retry + circuit-breaker
Standardized errors AppException hierarchy + register_exception_handlers
Per-level logs + /logs configure_logging(log_dir=…) + make_logs_router

Suggested structure

marketplace/
β”œβ”€β”€ main.py
β”œβ”€β”€ docker-compose.yaml
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ alembic/
└── src/
    β”œβ”€β”€ api/
    β”‚   β”œβ”€β”€ app.py
    β”‚   β”œβ”€β”€ routers/
    β”‚   β”‚   β”œβ”€β”€ auth.py            # signup + login + refresh
    β”‚   β”‚   β”œβ”€β”€ organizations.py   # CRUD org + members
    β”‚   β”‚   β”œβ”€β”€ invitations.py     # invite / accept / revoke
    β”‚   β”‚   β”œβ”€β”€ catalog.py         # public navigation
    β”‚   β”‚   β”œβ”€β”€ products.py        # product + variant CRUD (org-only)
    β”‚   β”‚   β”œβ”€β”€ stock.py           # in / out / adjust
    β”‚   β”‚   β”œβ”€β”€ cart.py            # buyer cart
    β”‚   β”‚   β”œβ”€β”€ orders.py          # checkout + status
    β”‚   β”‚   └── reviews.py         # post-delivery reviews
    β”‚   └── dependencies/
    β”‚       β”œβ”€β”€ auth.py            # current_user, require_org_role
    β”‚       └── controllers.py
    β”œβ”€β”€ controllers/               # cross-service orchestration
    β”œβ”€β”€ services/                  # domain logic
    β”œβ”€β”€ schemas/                   # Pydantic DTOs
    β”œβ”€β”€ core/                      # settings + exceptions + constants
    β”œβ”€β”€ db/
    β”‚   β”œβ”€β”€ models/                # ORM
    β”‚   └── repositories/          # queries
    β”œβ”€β”€ queue/                     # FastStream consumers
    β”œβ”€β”€ tasks/                     # TaskIQ tasks
    └── utils/
  1. Auth β€” UserModel(BaseUserModel) + UserTokenModel(BaseUserTokenModel) + wire UserAuthService + make_auth_router. Five endpoints ready: /auth/signup, /auth/activate/{token}, /auth/login, /auth/password-reset/request, /auth/password-reset/confirm. (Covers: abstract model concretization, bundled flow, JWT pair, Jinja2 templates.) See Auth flow recipe Β».
  2. Organizations + members β€” Organization + Membership with the 2-orgs-per-user / 10-members-per-org guard. (Covers: domain invariants, role-based access.)
  3. Invitations β€” Invitation with opaque token, Jinja2 email, 7-day expiry. (Covers: transactional email.)
  4. Catalog + products β€” Product + ProductVariant + PriceHistory. (Covers: 1-N relationships, soft-delete.)
  5. Stock β€” StockMovement (append-only) + balance derived via view or aggregate query. (Covers: auditing, transactions.)
  6. Cart + checkout β€” Cart + Order + OrderItem with idempotency. (Covers: state machine, idempotency.)
  7. Real-time status via SSE β€” event stream for status changes. (Covers: SSE.)
  8. Product images β€” upload via UploadUtils + MinIOUploadStorage + listing with presigned URL. (Covers: storage.)
  9. Async notifications β€” TaskIQ sending emails + RabbitMQ publishing events to projections / reports. (Covers: queues, tasks.)
  10. Metrics + admin β€” Prometheus endpoint + /admin listing entities. (Covers: observability, SDK admin.)

Each step ships one complete vertical slice β€” one feature end-to-end before adding the next.