Tech Stack

Every choice has a reason.

No framework roulette. Each layer was chosen for what B2B and B2C commerce both demand at scale — performance, async I/O, type safety, and real extensibility.

FastAPI

FastAPI

Backend framework

Async from the ground up. Native Pydantic validation on every request. Auto-generated OpenAPI docs in dev. FastAPI handles thousands of concurrent connections without breaking a sweat — critical when your storefront, admin panel, and integrations are all hitting the same API.

Why not Django/Flask: synchronous by default. Retrofitting async onto a sync framework is duct tape.

GraphQL

Strawberry GraphQL

API layer

Type-safe Python-first GraphQL. The schema is composed from domain modules — each module registers its own queries and mutations. Storefronts fetch exactly the data they need in one round trip. No over-fetching, no REST endpoint sprawl.

Why not REST: commerce frontends need flexible data shapes. A product page with pricing tiers, inventory per warehouse, and account-specific visibility is one query, not five — whether it's a wholesale portal or a retail storefront.

PostgreSQL

PostgreSQL 16

Transactional data

The database that doesn't surprise you at 3am. ACID transactions, JSONB for flexible metadata, row-level security, and partitioning for large catalogs. SQLAlchemy 2.0 async with Alembic migrations — the ORM that gets out of the way.

Why not MongoDB: commerce pricing is relational. Five pricing tiers referencing accounts, locations, and customer groups is a JOIN problem, not a document problem.

SvelteKit

SvelteKit

Admin & Storefront

Both the admin panel and the buyer-facing storefronts are SvelteKit apps. Server-side rendering for SEO, BFF pattern with httpOnly cookies for security, Svelte 5 reactivity, Paraglide JS for type-safe i18n, LayerChart for visual dashboards, TanStack Virtual for 1000+ row tables. Tailwind CSS 4.

Why not Next.js/React: smaller bundles, less boilerplate, faster renders. Paraglide's compile-time i18n means zero runtime overhead for translations.

Temporal

Temporal

Durable workflows

Order approval chains, recurring order scheduling, and multi-step fulfillment flows that survive crashes, restarts, and deployments. Workflows are code, not YAML — version them, test them, debug them like any other module.

All workflows and background tasks unified under Temporal — durable business processes and scheduled jobs through a single system with full visibility.

Redpanda

Event streaming

Kafka-compatible but without the JVM tax. When an order is placed, inventory, notifications, fulfillment, and analytics all react in parallel through event topics. Decoupled modules, no cascading failures, full replay capability.

Why not RabbitMQ: topic-based fan-out, persistent log, replay from any offset. Event sourcing needs a log, not a queue.

Redis

Redis

Cache & sessions

Pricing resolution is one of the most expensive operations in commerce — five tiers with volume breaks, evaluated per line item. Redis caches resolved prices so the second request for the same account + product is sub-millisecond. Also backs BFF sessions.

Typesense

Typesense + Meilisearch

Dual search engines

Typesense powers storefront product search with scoped API keys for catalog visibility. Meilisearch handles admin search. Both are typo-tolerant, faceted, and sub-50ms. No Elasticsearch cluster to babysit.

Why dual: storefront search needs scoped keys per buyer. Admin search needs full access. Different security models, different engines.

Architecture

Modular monolith. Event-driven core.

38 domain modules behind a single GraphQL endpoint. Clean service boundaries internally, zero microservice overhead externally.

GraphQL API

Strawberry GraphQL with async resolvers. Type-safe schema composed from 38 domain modules. One endpoint, full B2B and B2C surface area.

POST /graphql
GET /health

Data & Cache

PostgreSQL 16 for transactional data. Redis for session cache and pricing resolution. Typesense + Meilisearch for search. MinIO (S3-compatible) for file and media storage.

SQLAlchemy 2.0 async
Alembic migrations
Pydantic v2 schemas

Events & Workflows

Redpanda (Kafka-compatible) for event streaming via a dedicated consumer process. Temporal worker for durable workflows like approvals and recurring orders. In-process event bus for module communication.

order.placed → inventory
order.placed → notifications
order.placed → fulfillment
Clients
Admin SvelteKit :5173
B2B Storefront SvelteKit :5174
B2C Storefront SvelteKit / any
BFF · httpOnly cookies · Channel-aware
Channel Router

Routes requests to the correct channel · Applies pricing, visibility, and checkout rules per channel

GraphQL API :8000

FastAPI + Strawberry · 36 domain modules · Strategy pattern

PostgreSQL
Redis
Redpanda
Temporal
Typesense
Meilisearch
MinIO (S3)
Geo (ISO 3166)

Modules

38 domains. One codebase.

Every module is self-contained with its own models, services, resolvers, and events. Clean boundaries enforced by convention — no cross-module SQL.

AccountsMulti-tenant, locations, employees
ProductsVariants, brands, categories
Pricing5-level tiers, volume breaks
OrdersConfigurable state machine
CartPer-location, snapshots
InventoryMulti-warehouse stock
FulfillmentBoxing first, carrier strategies
PaymentsAuth/capture, saved cards, fraud
TaxSales + excise, multi-strategy
Promotions25+ conditions, 8 actions, stacking
ApprovalsTemporal-powered workflows
Net TermsNet-30/60, invoicing
QuotesRFQ with Temporal lifecycle
RMA / ReturnsLine-level, approval gates
Sales RepsTerritories, pipeline
Store CreditLedger-based balance
SearchTypesense + Meilisearch, scoped
CMSPages, blocks, navigation
TagsFlexible entity tagging
NotificationsEmail, SMS, in-app
ReportingLayerChart dashboards, exports
Recurring OrdersScheduled reorders
Catalog VisibilityPer-account product access
Audit TrailFull change history
AuthRBAC, 2FA, social OAuth
MarketingCampaigns, abandoned carts, email
Gift CardsBalance, redemption, ledger
ComplianceAge, tobacco, restricted SKUs
Support ChatIn-app messaging, sales rep
PlatformChannels, storefronts, branding
TrackingAfterShip events, status pings
BannersStorefront announcements, promos
FraudRules, blocklist, review queue
ActivityCustomer and system events
AIRich text editor, AI prompts
FeesPackage protection, surcharges
RegistrationForm builder, approval workflows
i18nParaglide JS, compile-time
Geo (ISO)Countries, regions, counties
GeolocationIP lookup, geocoding, validation
ChannelsB2B + B2C, per-channel rules
ExtensionsEntry points, per-storefront

Extensible

Extend without forking.

Vectis uses Python entry points for a true plugin architecture. Add custom tax providers, carrier integrations, compliance checks, or entirely new modules without touching core code. Extensions are scoped per storefront — your B2B store can run tobacco compliance while your B2C store doesn't.

Per-Storefront Extensions

Extensions activate per storefront. Different storefronts get different capabilities — no global on/off switches.

Strategy Registration

Register pricing, tax, and shipping strategies via entry points. The core discovers them at boot.

Event Hooks

Subscribe to domain events (order.placed, account.created) to trigger custom workflows.

41 Bundled Extensions

Payment, shipping, AI providers, fraud scoring, e-signatures, address validation, file storage, marketing, age verification, SSO, package protection — all ship out of the box.

pyproject.toml
# 41 extensions — payment, shipping, AI, fraud, address, storage, and more
# Payment
authorize_net nmi ach manual_payment
# Shipping
ups fedex usps usps_flatrate goshippo
shipstation ontrac priority1 aftership
# Address validation
smarty shipstation_address google_maps
# AI
anthropic claude openai chatgpt grok
# Fraud & compliance
signifyd riskified ipqs radar
agechecker
# Storage
s3 minio digitalocean_spaces dropbox
# E-signatures
docusign hellosign
# Marketing & messaging
omnisend elastic_email ses sns twilio
# Auth, geo, tax, commerce
keycloak maxmind exciseiq gift_cards package_protection

We tried the alternatives.

Open-source frameworks and hosted SaaS giants — great for B2C. Here's where they stop.

Capability Open-source / hosted SaaS Vectis
Multi-location accounts Not in data model Core
Tiered B2B pricing Plugin / manual 5-level, cached
Net terms & invoicing Build it yourself Core
Approval workflows Not available Temporal-powered
Swap pricing / tax / shipping logic Fork the core Strategy pattern
Catalog visibility per account Plugin Core
Event-driven architecture Hooks / basic events Redpanda + EventBus
Durable business workflows Not available Temporal
B2B + B2C from one engine Pick one Channels
Multi-strategy tax (sales + excise) Single provider resolve_all pipeline
ISO geographic data (seeded) String fields FK-based, ISO 3166
IP geolocation + address validation Extension / paid only Core (MaxMind free)
Fraud scoring (IP distance, VPN detection) Not available Async via Temporal
3D bin packing engine Not available Built-in + fallback
Auth/capture + auto void/refund Basic charge only Full lifecycle
RBAC + 2FA + social login Basic roles Granular + TOTP + OAuth
Age verification Not available AgeChecker.net
AI content editing Not available Claude, ChatGPT, OpenAI
B2B registration + e-signatures Not available Form builder + DocuSign
Pluggable file storage Local only S3, MinIO, DO Spaces
Composable promotions engine Coupon codes only 25+ conditions · 8 actions
Volume-tiered B2B discounts Not available Native rule type
Stacking policy + mutually-exclusive rules Manual / none Built-in
Boxing-first shipping model Duplicate box configs per carrier Define once, assign to providers
Bundled extensions 3-5 41 and growing