Additional SQL Server features and topics not covered by specific categories
Use plain proc exec (not serializable). Serializable silently reverts to millions of row-by-row DML commands if any call runs outside a serializable transaction - the exact volume you're avoiding. You've waived consistency, so plain proc exec is simpler with no such failure mode.
Why it won't break replication: your EXEC bypasses the default per-row delete procs that raise "row not found" (20598). A Publisher-only in-range row just matches nothing on the Subscriber no error, no stall.
Pattern bounded ranges, looped EXEC (the loop isn't replicated, each EXEC is):
CREATE PROCEDURE dbo.usp_DeleteByRange @RangeStart BIGINT, @RangeEnd BIGINT
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM dbo.YourTable
WHERE YourKeyColumn BETWEEN @RangeStart AND @RangeEnd; -- DateKey or PK
END;
DECLARE @lo BIGINT = 1, @hi BIGINT = 50000000, @batch BIGINT = 20000;
WHILE @lo <= @hi
BEGIN
EXEC dbo.usp_DeleteByRange @lo, @lo + @batch - 1;
WAITFOR DELAY '00:00:01';
SET @lo += @batch;
END;
Rules:
Pass bounds as literal parameters so no GETDATE() inside the proc (it re-evaluates on the Subscriber).
Index the predicate on both sides - the Subscriber re-runs the same delete; an unindexed scan there is your main latency risk.
Keep the proc minimal and batches small (lock/log control).
DateKey (YYYYMMDD) isn't contiguous - step by PK range, or by actual distinct DateKeys.