History and context
What actually needs to scale
Traffic is only one dimension. A platform can process high request volume and still fail organisationally if every new promotion or fulfilment rule requires changes across several applications.
Technical scale
Requests, connections, database load, cache pressure, queue throughput.
Business scale
Products, locations, pricing rules, fulfilment types, channels and teams.
Reference architecture
Why Next.js at the experience layer
Next.js provides an application framework around React and currently supports both App Router and Pages Router, with App Router being the newer model built around modern React capabilities. For commerce, the architectural benefit is the ability to choose server-rendered and client-interactive boundaries per feature rather than turning the whole storefront into a client-only application.
export default async function ProductPage({
params
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params;
const product = await getProduct(slug);
return (
<main>
<ProductSummary product={product} />
<AddToCart productId={product.id} />
</main>
);
}Why ASP.NET Core owns business rules
The backend should answer business questions rather than merely expose tables.
[HttpPost]
public async Task<ActionResult<CheckoutResult>> Checkout(
CheckoutRequest request,
CancellationToken cancellationToken)
{
var result = await checkoutService.ExecuteAsync(
request,
cancellationToken);
return Ok(result);
}Transactional modelling with PostgreSQL
Orders should store financial snapshots so later catalogue changes do not rewrite history.
CREATE TABLE sales_order (
order_id BIGSERIAL PRIMARY KEY,
order_number VARCHAR(40) NOT NULL UNIQUE,
status VARCHAR(30) NOT NULL,
subtotal NUMERIC(18,2) NOT NULL,
discount_amount NUMERIC(18,2) NOT NULL DEFAULT 0,
tax_amount NUMERIC(18,2) NOT NULL DEFAULT 0,
total_amount NUMERIC(18,2) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);Caching where it has a freshness policy
Redis can reduce repeated expensive reads, but every cached object needs an explicit invalidation or expiration policy. ASP.NET Core also provides distributed and hybrid caching abstractions for multi-instance applications.
var product = await hybridCache.GetOrCreateAsync(
$"product:{productId}",
async token => await repository.GetAsync(productId, token),
cancellationToken: cancellationToken);Keep the checkout critical path short
Idempotency protects money flows
Network timeouts do not prove that a payment failed. Retrying a non-idempotent checkout can create duplicates.
POST /api/checkout
Idempotency-Key: 9b86c74d-bd59-4e88-8718-208c6bb90872Indexes should follow real queries
SELECT product_id, product_name, fixed_price
FROM product
WHERE shop_id = @shopId
AND category_id = @categoryId
AND is_active = TRUE
ORDER BY product_name
LIMIT 24;CREATE INDEX ix_product_shop_category_active_name
ON product (shop_id, category_id, product_name)
WHERE is_active = TRUE;Indexes improve selected read patterns by adding write and storage cost. Performance work should start from measured query plans rather than index count.
Business value and practical considerations
Pros
- Strong multi-channel foundation
- Server/client rendering flexibility
- Relational transaction model
- Independent cache strategy
- Clear growth path
Considerations
- More engineering than hosted commerce
- Requires DevOps discipline
- Cache invalidation complexity
- Cloud and database cost governance
References
Primary documentation used for terminology and current platform guidance: