Skip to content

Vendure

Developer Productivity

An open‑source headless commerce platform built with Node.js, NestJS, and GraphQL.

TypeScript Latest v3.7.1 · 12d ago Security brief →

Features

  • Plugin‑first architecture for deep extensibility without code forks
  • Single TypeScript backend serving D2C, B2B, marketplace, and omnichannel via GraphQL
  • Built‑in commerce modules (catalog, orders, customers, promotions, tax, shipping, payments)
  • Production‑ready with high‑transaction performance

Recent releases

View all 12 releases →
No immediate action
v3.7.1 Breaking risk

Core, Dashboard, create, email-plugin, DataLoader

Upgrade now
v3.7.0 Breaking risk
Auth

CLI tools, Dashboard extensions, Security hardening

Upgrade now
v3.6.5 Security relevant
Auth RBAC

XSS fix + DoS mitigation + Dashboard & core updates

Review required
v3.6.4 Breaking risk
RBAC RCE / SSRF

graphql revert, security hardening, dashboard fixes, perf wins

v3.6.3 Bug fix
Notable features
  • Romanian translations added to the dashboard
  • Bulk cancel action with human‑readable duration strings
Full changelog

Highlights

This patch release lands a substantial round of stability, concurrency and dashboard fixes. The headline items address race conditions in promotion and coupon handling, prevent out-of-memory issues on large channel assignments, and harden the scheduled-task and state-machine subsystems against duplicated or partially-applied work. Thanks as ever to everyone who reported issues and contributed PRs.

Concurrency and integrity fixes

This release closes several long-standing edge cases that could cause data integrity issues under load or concurrent traffic:

  • Coupon usage limits enforced under concurrent checkout (#4660) -- A race condition allowed customers to bypass the per-coupon usage limit when multiple checkouts completed concurrently. The check is now serialised correctly so the configured limit is always respected.
  • Auto-applied promotion usage limits enforced (#4405) -- Promotions that auto-apply (no coupon code required) were not honouring their configured usage limits. They now respect the same limits as code-applied promotions.
  • Atomic state-machine transitions on hook failure (#4689) -- If a state-transition hook threw after the entity state had been written, the entity could be left in an inconsistent state with hooks partially applied. Transitions are now atomic — a failing hook reverts the state change cleanly.
  • No duplicate execution of fast scheduled tasks (#4681) -- Scheduled tasks running on a short interval could be picked up and executed by multiple workers in the same window. The scheduler now correctly deduplicates these executions.

Performance and scalability

  • Avoid OOM on large product-to-channel operations (#4669) -- assignProductsToChannel and removeProductsFromChannel now use a query relation strategy that no longer hydrates the full product graph into memory. This unblocks customers who hit out-of-memory crashes when assigning thousands of products to a channel.
  • Job queues now created in onModuleInit (#4680) -- Moving job-queue creation from onApplicationBootstrap to onModuleInit means queues exist before any other module's bootstrap code runs, eliminating a class of "queue not found" startup races.

Core fixes

  • Asset update with custom field relations (#4696) -- Updating an Asset that had a custom-field relation defined no longer fails. This pairs with the corresponding dashboard fix (#4695).
  • Entity hydrator handles undefined relations (#4672) -- Hydrating an entity where a requested relation was undefined no longer throws.
  • Customer user resolution via relation (#4468) -- The Customer.user resolver now uses the configured relation instead of doing a separate email-based lookup, fixing edge cases where the email had been changed on the user record.
  • Admin UI handles tokenMethod array form (#4663, fixes #4656) -- When tokenMethod is configured as an array (['cookie', 'bearer']), the generated ui-config now serialises it correctly instead of producing an invalid value.

Dashboard fixes and improvements

  • Asset save with custom fields (#4695) -- Saving an Asset with custom fields defined now works correctly from the dashboard.
  • Action bar positioning relative to extensions (#4676) -- Extensions can now position action bar items relative to other extensions rather than only to built-in items, giving extension authors more control over toolbar layout.
  • Graceful fallback on denied replace-extension (#4694) -- When a permission check denies a replace-style extension, the dashboard now falls back to the original block instead of rendering nothing.
  • Custom-page permission checks (#4679) -- Custom pages now respect their declared requiredPermissions and won't render for users who lack them.
  • isFullWidth metadata prop implemented (#4638) -- PageBlocks can now opt into a full-width layout via metadata, useful for components like rich text editors.
  • Direct @base-ui/react imports dropped (#4697) -- Dashboard internals no longer import directly from @base-ui/react, going through the wrapped component layer instead. This keeps the public surface area consistent for extension authors.
  • Order modification preview includes nested fragments (#4640) -- Modification previews now include all required nested fields, so the preview matches what the modification will actually produce.
  • Draft order mutation error messages (#4381) -- updateOrder* mutations on draft orders now surface their error messages to the UI rather than failing silently.
  • Promotions list default sort (#4688) -- The promotions list now opens with a sensible default sort instead of arbitrary order.
  • Chart widget dynamic Y-axis width (#4516) -- The dashboard chart widget now sizes its Y-axis dynamically so long labels are no longer clipped.
  • Empty customFields selection handled (#4652) -- Custom-field components with no selection no longer throw.
  • Fulfillment arg defaults are strings (#4658) -- Fulfillment handler argument default values are now correctly stringified.
  • Tanstack router generator stability (#4666) -- Inlining the route literal sidesteps a tanstack router-generator quirk that could produce broken route trees in certain layouts.

New dashboard features

  • Bulk cancel action with human-readable durations (#4361) -- Order lists now expose a bulk-cancel action, and durations are rendered as human-readable strings (e.g. "3 days ago") rather than raw timestamps.
  • Romanian translations (#4598) -- Romanian (ro) is now supported in the dashboard.

i18n improvements

  • Italian translations updated (#4645) -- A round of missing Italian (it) strings has been added.
  • Swedish corrections (#4684) -- Several mistranslated Swedish (sv.po) strings have been corrected.
  • Wrong-language msgstrs repaired (#4685) -- A bulk fix across hr, nb, tr, it, ja, ko, he and ro removes msgstr entries that had drifted into the wrong language. The i18n:apply script has been hardened to prevent recurrences.

Plugins

  • BullMQJobQueuePlugin filtering (#4523) -- Job filtering in the BullMQ plugin now produces correct results when combining multiple filter fields.

What's Changed

  • fix(ci): Remove [skip ci] from generate_docs workflow by @oliverstreissi in https://github.com/vendurehq/vendure/pull/4646
  • fix(ci): Add gate job to unblock non-package PRs by @michaelbromley in https://github.com/vendurehq/vendure/pull/4649
  • fix(docs): Fix broken links and outdated type names in custom form components docs by @gabriellbui in https://github.com/vendurehq/vendure/pull/4648
  • docs: Fix typo in navigation-menu arrayToTree code snippet by @gabriellbui in https://github.com/vendurehq/vendure/pull/4593
  • fix(core): Enforce usage limits for auto-applied promotions by @HouseinIsProgramming in https://github.com/vendurehq/vendure/pull/4405
  • fix: Add missing include nested fragments in order modification preview by @Ryrahul in https://github.com/vendurehq/vendure/pull/4640
  • fix: Add dynamic y axis width by @Ryrahul in https://github.com/vendurehq/vendure/pull/4516
  • feat(dashboard): Add Romanian translations by @alingabrieldm in https://github.com/vendurehq/vendure/pull/4598
  • fix: Add recursive flatten job filter for bull mq when filter is sent… by @Ryrahul in https://github.com/vendurehq/vendure/pull/4523
  • fix: Make tab view scrollable by @Ryrahul in https://github.com/vendurehq/vendure/pull/4644
  • feat(dashboard): Add bulk cancel action and human-readable duration t… by @Ryrahul in https://github.com/vendurehq/vendure/pull/4361
  • chore: Bump @vendure-io/docs-generator to 0.1.1 by @michaelbromley in https://github.com/vendurehq/vendure/pull/4664
  • fix(admin-ui): Handle tokenMethod array form when generating ui-config (#4656) by @Draykee in https://github.com/vendurehq/vendure/pull/4663
  • fix(dashboard): Inline route literal for tanstack router-generator by @michaelbromley in https://github.com/vendurehq/vendure/pull/4666
  • fix(core): Avoid OOM in product-to-channel assign/remove via query relation strategy by @arthur-nesterenko in https://github.com/vendurehq/vendure/pull/4669
  • chore: Migrate package management from npm to Bun by @michaelbromley in https://github.com/vendurehq/vendure/pull/4675
  • fix(core): Create job queues in onModuleInit instead of onApplicationBootstrap by @michaelbromley in https://github.com/vendurehq/vendure/pull/4680
  • fix(core): Prevent coupon usage limit bypass via concurrent checkout race condition by @grolmus in https://github.com/vendurehq/vendure/pull/4660
  • fix(core): Resolve customer user via relation instead of email lookup by @grolmus in https://github.com/vendurehq/vendure/pull/4468
  • fix(dashboard): Support action bar positioning relative to extensions by @izumi0uu in https://github.com/vendurehq/vendure/pull/4676
  • chore: Add local asset storage strategy and its factory to exports by @DanielBiegler in https://github.com/vendurehq/vendure/pull/4671
  • fix(core): Handle undefined relation in entity hydrator by @izumi0uu in https://github.com/vendurehq/vendure/pull/4672
  • fix(dashboard): Handle empty customFields selection when all fields h… by @Ryrahul in https://github.com/vendurehq/vendure/pull/4652
  • fix(dashboard): Add missing Italian translations by @claudiolor in https://github.com/vendurehq/vendure/pull/4645
  • feat(dashboard): implement isFullWidth metadata prop by @casperiv0 in https://github.com/vendurehq/vendure/pull/4638
  • fix(dashboard): Repair wrong-language msgstrs across hr/nb/tr/it/ja/ko/he/ro and harden i18n:apply by @michaelbromley in https://github.com/vendurehq/vendure/pull/4685
  • fix(dashboard): correct mistranslated Swedish strings in sv.po by @comega-johan in https://github.com/vendurehq/vendure/pull/4684
  • fix(dashboard): Ensure fulfillment arg default value is a string by @kyunal in https://github.com/vendurehq/vendure/pull/4658
  • chore(dashboard): Add error messages to update draft mutations by @LucidityDesign in https://github.com/vendurehq/vendure/pull/4381
  • fix(core): Make state-machine transitions atomic on hook failure by @michaelbromley in https://github.com/vendurehq/vendure/pull/4689
  • fix(dashboard): set default sort on promotions list by @casperiv0 in https://github.com/vendurehq/vendure/pull/4688
  • fix(core): Prevent duplicate execution of fast scheduled tasks by @BibiSebi in https://github.com/vendurehq/vendure/pull/4681
  • fix(dashboard): Check required permissions when rendering custom page… by @LucidityDesign in https://github.com/vendurehq/vendure/pull/4679
  • fix(dashboard): Fall back to original on denied replace extension by @michaelbromley in https://github.com/vendurehq/vendure/pull/4694
  • fix(dashboard): Align asset mutation selection set with other detail pages by @michaelbromley in https://github.com/vendurehq/vendure/pull/4695
  • fix(core): Save Asset before running custom-field relation updates by @michaelbromley in https://github.com/vendurehq/vendure/pull/4696
  • chore(dashboard): Drop direct @base-ui/react imports by @michaelbromley in https://github.com/vendurehq/vendure/pull/4697

New Contributors

  • @arthur-nesterenko made their first contribution in https://github.com/vendurehq/vendure/pull/4669
  • @izumi0uu made their first contribution in https://github.com/vendurehq/vendure/pull/4676
  • @claudiolor made their first contribution in https://github.com/vendurehq/vendure/pull/4645
  • @comega-johan made their first contribution in https://github.com/vendurehq/vendure/pull/4684

Full Changelog: https://github.com/vendurehq/vendure/compare/v3.6.2...v3.6.3

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

About

Stars
8,255
Forks
1,447
Languages
TypeScript HTML SCSS
Downloads/week
5,246 ↓12%
NPM Maintainers
4
Contributors
100
TypeScript
Types included ✓

Community & Support

Beta — feedback welcome: [email protected]