Skip to main content

Currency

In Vendure, monetary values are stored as integers using the minor unit of the selected currency. For example, if the currency is set to USD, then the integer value 100 would represent $1.00. This is a common practice in financial applications, as it avoids the rounding errors that can occur when using floating-point numbers.

For example, here's the response from a query for a product's variant prices:

Json

In this example, the tax-inclusive price of the variant is $23.99.

Info

To illustrate the problem with storing money as decimals, imagine that we want to add the price of two items:

  • Product A: $1.21
  • Product B: $1.22

We should expect the sum of these two amounts to equal $2.43. However, if we perform this addition in JavaScript (and the same holds true for most common programming languages), we will instead get $2.4299999999999997!

For a more in-depth explanation of this issue, see this StackOverflow answer

Support for multiple currencies

Vendure supports multiple currencies out-of-the-box. The available currencies must first be set at the Channel level (see the Channels, Currencies & Prices section), and then a price may be set on a ProductVariant in each of the available currencies.

When using multiple currencies, the ProductVariantPriceSelectionStrategy is used to determine which of the available prices to return when fetching the details of a ProductVariant. The default strategy is to return the price in the currency of the current session request context, which is determined firstly by any ?currencyCode=XXX query parameter on the request, and secondly by the defaultCurrencyCode of the Channel.

Currencies are configured at the Channel level. Each channel defines which currencies are available and which is the default. This means different channels can operate in different currencies, making it straightforward to support multi-region stores. For more details, see the Channels guide.

Code Examples

Displaying monetary values

When you are building your storefront, or any other client that needs to display monetary values in a human-readable form, you need to divide by 100 to convert to the major currency unit and then format with the correct decimal & grouping dividers.

In JavaScript environments such as browsers & Node.js, we can take advantage of the excellent Intl.NumberFormat API.

Here's a function you can use in your projects:

src/utils/format-currency.ts

If you are building an Dashboard extension, you can use the built-in useLocalFormat hook:

src/plugins/my-plugin/dashboard/components/my-component.tsx

The GraphQL Money scalar

In the GraphQL APIs, we use a custom Money scalar type to represent all monetary values. We do this for two reasons:

  1. The built-in Int type is that the GraphQL spec imposes an upper limit of 2147483647, which in some cases (especially currencies with very large amounts) is not enough.
  2. Very advanced use-cases might demand more precision than is possible with an integer type. Using our own custom scalar gives us the possibility of supporting more precision.

Here's how the Money scalar is used in the ShippingLine type:

Graphql

If you are defining custom GraphQL types, or adding fields to existing types (see the Extending the GraphQL API doc), then you should also use the Money scalar for any monetary values.

The @Money() decorator

When defining new database entities, if you need to store a monetary value, then rather than using the TypeORM @Column() decorator, you should use Vendure's @Money() decorator.

Using this decorator allows Vendure to correctly store the value in the database according to the configured MoneyStrategy (see below).

src/plugins/quote/entities/quote.entity.ts

MoneyStrategy configuration

For advanced use-cases, it is possible to configure aspects of how Vendure handles monetary values internally by defining a custom MoneyStrategy.

The MoneyStrategy allows you to define:

  • How the value is stored and retrieved from the database
  • How rounding is applied internally
  • The precision represented by the monetary value (since v2.2.0)

For example, in addition to the DefaultMoneyStrategy, Vendure also provides the BigIntMoneyStrategy which stores monetary values using the bigint data type, allowing much larger amounts to be stored.

Here's how you would configure your server to use this strategy:

src/vendure-config.ts

Example: supporting three decimal places

Let's say you have a B2B store which sells products in bulk, and you want to support prices with three decimal places. For example, you want to be able to sell a product for $1.234 per unit. To do this, you would need to:

  1. Configure the MoneyStrategy to use three decimal places
Ts
  1. Set up your storefront to correctly convert the integer value to a decimal value with three decimal places. Using the formatCurrency example above, we can modify it to divide by 1000 instead of 100:
src/utils/format-currency.ts
Was this chapter helpful?
Report Issue
Edited Feb 23, 2026ยทEdit this page