When does batch sales tax calculation make sense, and when does it have to be real-time?

Sales tax calculation must run in real time on three flows: the cart-and-checkout display, payment authorization, and order persistence. Everything where no customer is waiting (B2B invoicing on net terms, marketplace settlement reconciliation, end-of-day ground-truth recalculation, historical backfill) can run on a batch path. Most $30-70M DTC brands run end-of-day batch alongside real-time checkout.

Last updated: Sep 10, 2026 Sales Tax at Scale Team

Key takeaways

  • The customer-experience boundary is the split point. Real-time on flows where a customer is waiting at checkout, batch on flows where no one is waiting: B2B invoices on net-30 terms, marketplace settlement files from Amazon, Walmart, and TikTok Shop, end-of-day ground-truth recalculation, and historical backfill.
  • The double-recording hazard is the month-end failure mode. The same logical order gets a real-time calculation at checkout and a batch calculation in the nightly job, and the tax engine carries two records for one order. Prevention is a single idempotency key shared across both paths, keyed to the order ID and the line items at calculation time.
  • A $30-70M DTC brand typically runs end-of-day batch for the ground-truth record and exception handling, with real-time on the checkout path. Hourly batch arrives around $100M when settlement file volume or B2B invoice cadence justifies it.
  • In-flight corrections that arrive before the batch window closes are netted within the window. Corrections arriving after the window closes carry to the next window as an explicit adjustment record. Cross-period corrections (a December refund posted in January for a Q4 order) need explicit flagging for prior-period adjustment.
  • The reconciliation pass is what makes the dual-path model defensible at audit. Without it, real-time and batch produce two records for one order with no link between them. With it, every customer-facing tax total has a ground-truth batch counterpart and a documented variance.
  • The single-API pattern is the standard at $30-70M. One calculation surface used in both real-time and bulk modes, with the same idempotency, jurisdiction logic, and rate source across the two paths, prevents the duplicate-integration failure mode that drives most reconciliation-variance work.

What's the difference between batch and real-time sales tax calculation?

Both patterns produce a tax amount on a transaction. They differ in when the calculation runs, who is waiting on the result, and which infrastructure layer carries the load. Six dimensions matter when an engineering team is splitting the calculation surface at a $20-80M DTC brand.

Dimension
Real-time
Batch
When it runs
Inline with the customer-facing transaction. The checkout request blocks on the tax response.
On a fixed cadence (hourly, end-of-day, end-of-month), pulling a window of transactions and producing tax results in bulk.
Who is waiting
The customer at the cart or checkout page.
No one. The job runs against persisted transactions on the back office's schedule.
Latency budget
150-300ms at p95 for the tax slice of a 1.5-3 second checkout target [1].
Minutes to hours, bounded by job duration and downstream filing deadlines, not customer wall-clock.
Infrastructure
Tax API on the checkout request path, with cached fallback and timeout handling.Tax API on the checkout request path, with cached fallback and timeout handling.
Bulk calculation endpoint, idempotency cache, reconciliation pass, writeback to the order or invoice record.
Failure handling
Fail-open with cached rate, fail-closed at the order layer, or post-order recalculation.
Retry with exponential backoff, dead-letter on terminal failure, manual reprocessing from the job log.
Instrumentation
Request rate, p95 latency, error rate at the API tier.
Job duration, records-processed-per-second, reconciliation variance count at the batch tier.

The two architectures are not mutually exclusive. At $30M the calculation layer is typically real-time on the DTC checkout and batch on a handful of back-office flows: settlement reconciliation, B2B invoice runs, end-of-day reconciliation. At $80M most brands run both paths simultaneously, with the batch path producing the ground-truth tax record that feeds reconciliation and filing. The engineering question is not "real-time or batch" but "which transactions belong on which path, and how do the two reconcile."

Which flows belong on real-time, and which belong on batch

The batch-versus-real-time decision splits cleanly by who is waiting. A customer at checkout needs the tax now, so the DTC checkout path is real-time. Nobody is waiting on a B2B invoice billed on net-30 terms, nobody is waiting on a marketplace settlement file that arrives daily from Amazon or Walmart, nobody is waiting on the end-of-day ground-truth recalculation that feeds the next month's filing. Those flows are batch. Brands that ran everything real-time paid for calculation capacity they did not need; brands that batched the checkout broke the customer experience. The split is not about cost or sophistication. It is about whether someone is staring at a screen waiting for the number.

Three flows require real-time calculation.

  1. DTC checkout display. The customer sees the exact tax line on the cart and checkout summary before completing the order. The calculation must resolve within the 150-300ms p95 budget that the broader 1.5-3 second checkout target allows for the tax slice[1]. Anything slower drags conversion at the moment of purchase.
  2. Payment authorization. The final amount sent to the payment processor at authorization must include tax. Authorizing $98.50 and then collecting $103.50 because tax was added post-auth is a payment-authorization mismatch, which most processors treat as a chargeback risk. The authorized amount has to be locked at the moment authorization fires.
  3. Order persistence at checkout. The tax amount displayed and authorized has to land on the persisted order before the order moves to fulfillment. Downstream systems (inventory reservation, fulfillment routing, customer notifications) read from the order record, and a missing or pending tax field there introduces ambiguity into the order lifecycle.

Four flows belong on the batch path.

  1. B2B invoicing on net terms. A B2B order invoiced net-30 does not need the tax line resolved at order entry. The invoice is the customer-facing artifact, and the tax line on the invoice can be calculated against the rates in effect at invoice time, not at order time. A nightly or weekly batch run against the day's pending invoices is the standard cadence.
  2. Marketplace settlement reconciliation. Settlement files from Amazon Selling Partner[3], Walmart Marketplace[4], and TikTok Shop arrive on the marketplace's schedule, typically daily, sometimes weekly. The brand's job is to tie each settlement line back to an order, capture the tax the marketplace already collected, and write the tax record into the brand's ground-truth log. No customer is waiting on this; it has to run before the close, not before the order.
  3. End-of-day ground-truth recalculation. The real-time checkout produces a customer-facing total under p95 budget pressure, which means cached rates and fail-open fallbacks come into play. The batch path runs the same orders through full taxability resolution and current rate tables, produces the ground-truth tax record, and writes any variance into the reconciliation log. The customer-displayed total never changes asynchronously; the ground-truth record does.
  4. Historical backfill. When a brand adds a new state to its filing footprint, registers retroactively, or onboards a new tax engine, the existing transaction history needs to be recalculated against the rate tables and taxability rules in effect at the original transaction date. This is a one-time or rare bulk job, run from a static order export, with no customer-facing latency requirement.

Platforms like TaxCloud expose a calculation API usable in both modes from a single integration: as the real-time endpoint the checkout extension calls on Shopify or Shopify Plus, and as the bulk endpoint the batch job iterates against for the back-office flows. The same idempotency, jurisdiction logic, and rate source apply across both paths, with no duplicate integration surface for the engineering team to maintain.

How real-time and batch interact without double-recording the same transaction

The double-recording hazard is the failure that shows up at month-end. The same logical transaction gets a real-time calculation at checkout and then a batch calculation in the nightly job, and the tax engine has two records for one order. At low volume the duplication shows up as a $20 variance on the reconciliation pass that nobody investigates. At $50M-plus volume the duplication becomes a structural problem: the calculation log overstates jurisdictional sales by the duplicate count, the SST filing pulled from that log overstates taxable receipts, and the controller's monthly close runs three days longer than it should because the reconciliation pass is chasing duplicates that should never have been written.

The fix is a single idempotency key, derived from inputs both paths can see, checked by both paths before write. The shape:

  1. Key inputs are stable across paths. The key hashes over the brand's internal order ID, the line items at calculation time (product or variant ID, quantity, unit price, taxability code), and the ship-to address. The real-time call hashes over those inputs at checkout; the batch call hashes over the same inputs from the persisted order record. If neither order nor line items have changed between the two events, both paths produce the same key. The semantics follow IETF RFC 9110 §9.2.2 on idempotent operations.[2]
  2. The batch path checks for an existing real-time record before writing. Before the batch worker writes a calculation result for an order, it looks up the idempotency key. If a real-time record already exists for that key, the batch worker either skips the write entirely (treating the real-time record as authoritative for the customer-displayed total) or writes a variance record that flags the difference for the reconciliation pass to resolve.
  3. The real-time path emits its key into the same idempotency cache the batch worker reads. This is the load-bearing detail. If the real-time and batch paths use separate idempotency caches, the check is theatre; both paths will still write. The cache has to be a single source of truth, typically a Redis or DynamoDB store keyed by the idempotency hash and indexed by order ID.
  4. The reconciliation pass catches anything the idempotency check missed. Cache evictions, partial failures, retries that hit a different cache region: any of these can produce a duplicate write that slipped the check. The reconciliation pass on the calculation log surfaces duplicate keys, paired calculation records on the same order ID, and any record where the real-time and batch results materially disagree.

The batch cadence a $30-70M DTC brand actually runs

The cadence brands actually run at $30-70M is end-of-day batch for reconciliation and exception handling, not real-time everywhere. The real-time path handles the customer-facing calculation at checkout. The batch path handles the ground-truth record and the corrections. Hourly batch shows up later, around $100M, when settlement file volume or B2B invoice cadence justifies the additional infrastructure. End-of-month batch is uncommon at the mid-market band; it surfaces in older NetSuite or QuickBooks Online setups where the brand has not yet pulled the calculation step out of the close cycle.

The cadence-by-revenue-band shape:

Revenue band
Typical batch cadence
What drives the cadence
Under $20M
End-of-day for marketplace settlements only; everything else stays on the real-time path or inside Shopify Tax.
Volume does not justify a separate back-office calculation pipeline. The brand has not yet outgrown the checkout-native tax surface.
$20-30M
End-of-day batch on settlement reconciliation, B2B invoice runs (if any), and the ground-truth recalculation.
First inflection. The brand registers in more states, adds B2B or wholesale, and the close starts to take longer than the controller can absorb.
$30-70M
End-of-day batch as the steady state, with the ground-truth recalculation feeding the next-day reconciliation pass and the next-month filing.
The dual-path pattern is now standard. Real-time for checkout, batch for everything else, and the reconciliation pass closes the loop.
$70-100M
End-of-day batch with hourly settlement processing for high-frequency marketplace flows.
Marketplace settlement files start arriving on a sub-daily cadence, especially as TikTok Shop and Walmart channels grow. B2B invoice runs may shift to twice-daily.
Over $100M
Hourly or sub-hourly batch for settlement, B2B invoicing, and variance detection; end-of-day batch reserved for the close-aligned reconciliation pass.
Volume and channel mix make the latency from order to ground-truth record material. The brand cannot afford to discover a multi-thousand-dollar reconciliation variance the morning of the close.

The cadence decision is not arbitrary. It is set by the slowest tolerable lag between the customer-facing transaction and the ground-truth record. End-of-day batch is the standard at $30-70M because the close is the natural cadence for the controller's exception-handling work. Pulling the cadence sub-daily before the brand has the operational surface to act on sub-daily exceptions just creates more reconciliation noise without faster decisions.

A well-designed calculation API runs in both real-time and bulk modes against the same idempotency cache and jurisdiction logic, which is what the dual-path pattern at this band requires. A brand running end-of-day batch iterates the bulk endpoint over the day's persisted orders, writes the calculation results to the order record alongside the existing real-time results, and pulls the variance count from the reporting API into the monthly close.

How the batch path handles in-flight corrections

In-flight corrections are the failure mode the batch path has to handle explicitly, not by default. A refund posted at 11:47pm on Tuesday lands in the same batch window as the original order from 8:14am Tuesday morning. An exchange posted at 11:47pm Tuesday for an order from Monday lands across windows. The rule that resolves the design choice is one sentence: net within the window where possible, carry to the next window with an explicit adjustment record where not.

Three correction patterns and how each is handled:

  1. Refund inside the same batch window. The original order and the refund both land in the day's batch run. The batch worker nets them within the window: the calculation log shows the original tax amount, the refund's tax reversal, and the net result. The reconciliation pass sees a paired record (one positive, one negative, same order ID), confirms the net to zero or to the partial-refund amount, and writes a single net-result entry to the close-aligned reconciliation log.
  2. Refund crossing batch windows. The original order ran through Monday's batch. The refund posts Tuesday at 11:47pm. The Tuesday batch picks up the refund as a standalone adjustment, looks up the original order by ID, writes a tax-reversal record linked to the original, and surfaces the cross-window adjustment in the reconciliation log. The original order's calculation record stays untouched; the adjustment is the artifact that closes the variance.
  3. Exchange or partial return crossing batch windows. Same shape as the cross-window refund, with the additional complexity that an exchange may produce both a tax reversal (on the returned item) and a new tax calculation (on the replacement item). The batch worker writes both as linked adjustments against the original order, the reconciliation pass surfaces the pair, and the controller decides whether the exchange is treated as a single net transaction or as a refund-plus-new-order pair for filing purposes.

The bigger the customer's downside risk on a correction, the bigger the upfront caveat. Multi-state corrections that cross filing periods (a December refund posted in January for a Q4 order) are the highest-stakes case. The refund's tax reversal hits a filing period that may already be closed, which forces a prior-period adjustment on the next filing or an amended return. The batch path has to flag these explicitly so the close-side workflow catches them before the filing goes out. How do you build sales tax audit-readiness into your monthly close? covers the close-side cadence that depends on a complete, on-time correction log.

The dual-path operating model at multi-state scale

The dual-path operating model is the steady state for a $30-70M DTC brand once the calculation surface has split. The real-time path handles the customer-facing calculation on Shopify, Shopify Plus, BigCommerce, or the custom checkout. The batch path handles the back-office flows: marketplace settlement reconciliation, B2B invoicing, end-of-day ground-truth recalculation, in-flight correction handling, historical backfill when needed. The reconciliation pass connects the two, surfaces variance between the real-time and batch results on a per-order basis, and produces the ground-truth calculation log that the monthly close and the next state filing draw from.

The operational properties the dual-path buys are:

  • Lower checkout latency. The real-time call is bounded by the 150-300ms p95 budget. The batch path absorbs the heavier work (full taxability resolution, multi-jurisdiction rate-table reads, audit-log persistence) off the customer-facing wall clock.
  • Decoupled engine availability. A tax-engine outage on the batch path produces a delayed reconciliation, not a checkout outage. The real-time path uses cached fallback when the API breaches its budget. The batch path catches up when the engine recovers.
  • A ground-truth record built on its own path. The batch-produced calculation log is the document filing and audit are built on. Producing it as a separate path, rather than as a side effect of the real-time call, surfaces calculation lag and rate-source variance as observable metrics rather than reconciliation anomalies discovered at month-end.

At a multi-state, multi-channel steady state, the question is no longer whether to split real-time and batch. It is what the operating model looks like once you do. Platforms like TaxCloud handle this through a single calculation API usable in both real-time and bulk modes, native Shopify, Shopify Plus, and BigCommerce integration on the real-time path, idempotency support shared across both paths, and a reporting API that exposes the per-order calculation log for the batch reconciliation that closes the loop.

Sources

  • Shopify

    Checkout UI extensions: timeouts and performance requirements

    Source link
  • RFC Editor

    RFC 9110, HTTP Semantics §9.2.2 (Idempotent Methods), R. Fielding et al., June 2022

    Source link
  • Amazon Services LLC

    Selling Partner API: Reports API and Settlement Reports

    Source link
  • Walmart Marketplace

    Seller Center Reports: Settlement Report reference

    Source link

FAQ

Common questions

When should sales tax calculation run in batch versus real-time on a Shopify Plus DTC stack?

Real-time on the customer-facing checkout flows: cart-and-checkout display, payment authorization, and order persistence. The customer needs the tax line resolved within the checkout's 150-300ms p95 latency budget. Batch on the back-office flows: marketplace settlement reconciliation, B2B invoicing on net terms, end-of-day ground-truth recalculation, and historical backfill. Most $30-70M DTC brands run end-of-day batch alongside real-time checkout, with a shared idempotency key preventing double-recording across the two paths.

What batch cadence does a $30-70M DTC brand typically run?

End-of-day. The real-time path handles customer-facing calculations during the day. The batch path runs after close-of-business, processes marketplace settlement files, regenerates the ground-truth tax record on the day's orders, and produces the reconciliation log that feeds the monthly close. Hourly batch arrives around $100M when settlement file volume or B2B invoice cadence justifies it. End-of-month batch is uncommon at this band and usually a sign the calculation step has not been pulled out of the close cycle.

How do you prevent the real-time and batch paths from double-recording the same transaction?

Shared idempotency key derived from the order ID, the line items at calculation time (product or variant ID, quantity, unit price, taxability code), and the ship-to address. Both paths emit and check the same key against a single source-of-truth cache (typically Redis or DynamoDB) before writing. The batch worker looks up the key, sees the real-time record already exists for that order, and either skips the write or writes a variance record for the reconciliation pass to resolve. A reconciliation pass on the calculation log catches anything cache eviction missed.

How does the batch path handle refunds or exchanges that arrive before the batch window closes?

Within the window, the batch worker nets them as paired records: original order calculation plus refund tax reversal, surfaced together in the reconciliation log. Across windows, the batch worker treats the refund as a standalone adjustment, looks up the original order by ID, writes a tax-reversal record linked to the original, and flags the cross-window adjustment for the close-side workflow. Cross-period adjustments (a December refund posted in January for a Q4 order) need explicit flagging so the close catches them before the filing goes out.

Which flows actually belong on a batch path?

B2B invoicing on net terms (the customer-facing artifact is the invoice, not the order, so the tax line can resolve at invoice time). Marketplace settlement reconciliation from Amazon, Walmart, and TikTok Shop (settlement files arrive on the marketplace's daily or weekly cadence). End-of-day ground-truth recalculation against full taxability rules and current rate tables (the customer-displayed total stays authoritative; the ground-truth record updates). Historical backfill when registering retroactively or onboarding a new tax engine. Everything else stays on the real-time path.

Does running batch tax calculation create audit exposure?

Not by itself. Auditors look for completeness of the calculation log, not whether every rate came from a real-time call. A log that records the rate applied, the jurisdiction stack, the calculation timestamp, the rate-source identifier, and the idempotency key, with the reconciliation log closing any real-time-versus-batch variance, is the defensible documentation pattern. The audit exposure surfaces when batch jobs lag without instrumentation and the ground-truth record is incomplete at filing time, or when in-flight corrections cross periods without being flagged for prior-period adjustment.