powershelldba.de

Add Articles to Existing Replication Without Reinitializing the Snapshot

Adding one table to a transactional publication shouldn't mean re-copying every other table that's already replicating fine. Here's how to add a new article and have only that article snapshotted, while every existing subscription keeps running untouched.

Why This Matters

The default instinct, and what SSMS will offer to do if you click through the Publication Properties dialog without reading the prompt, is to mark the whole publication for reinitialization. That triggers a full new snapshot of every article and a full bulk copy of every published table to every subscriber, not just the new one.

On a publication with a handful of small lookup tables, that's a non-event. On a publication that's been running for years with large transactional tables, it means hours of snapshot generation, a distribution database that balloons with BCP files, subscribers that fall behind while they re-absorb tables they already had, and a maintenance window you didn't need for what should have been a one-table change.

SQL Server has supported adding an article without a full reinitialization since replication got serious in 2005, but the option is easy to miss because the GUI default doesn't lead you there.

The Two Parameters That Matter

Everything hinges on how you call sp_addarticle:

ParameterEffect
@force_invalidate_snapshot Acknowledges that adding this article changes the publication's snapshot contents. Required (set to 1) whenever you add an article to a publication that already has active subscriptions, otherwise sp_addarticle raises an error telling you to reinitialize.
@force_reinit_subscription Controls whether existing subscriptions get marked for a full reinitialization. Left at its default (0), existing subscriptions are left alone. Set it to 1 and you're back to the expensive full-reinit path this article is trying to avoid.
The mechanism in one sentence: @force_invalidate_snapshot = 1 with @force_reinit_subscription left at 0 tells the Snapshot Agent "yes, generate a new snapshot, but don't tell existing subscribers they need to start over." The Distribution Agent then delivers the new article's initial data to subscribers because that article's subscription is brand new and has no sync history yet, while it skips the already-synchronized articles entirely.

Step by Step (Transactional Replication)

1. Add the article

USE [PublicationDB];
GO

EXEC sp_addarticle
    @publication              = N'MyPublication',
    @article                  = N'NewOrderDetails',
    @source_owner             = N'dbo',
    @source_object            = N'NewOrderDetails',
    @type                     = N'logbased',
    @force_invalidate_snapshot = 1;
GO

2. Add it to the existing subscriptions

EXEC sp_addsubscription
    @publication = N'MyPublication',
    @article     = N'NewOrderDetails',
    @subscriber  = N'ALL',
    @reserved    = N'Internal';
GO

@subscriber = N'ALL' applies the new article to every subscriber already subscribed to the publication, which is what you want in almost every case: you're extending what's already flowing, not standing up a new subscriber.

3. Run the Snapshot Agent once

EXEC sp_startpublication_snapshot @publication = N'MyPublication';
-- or trigger the Snapshot Agent job from SQL Server Agent / Replication Monitor

This scripts the schema for every article (harmless, it's just .sch/.idx files on disk) but only generates a data snapshot the Distribution Agent will actually apply for the newly added article. Watch the agent history: existing tables should show as already synchronized, and only NewOrderDetails should show rows being bulk copied.

4. Verify

-- Confirm the article is attached
EXEC sp_helparticle @publication = N'MyPublication', @article = N'NewOrderDetails';

-- Confirm subscriptions picked it up
EXEC sp_helpsubscription @publication = N'MyPublication', @article = N'NewOrderDetails';

-- On the subscriber, confirm the table exists and has data
SELECT COUNT(*) FROM dbo.NewOrderDetails;

Then check the Distribution Agent's session history in Replication Monitor for one full cycle: it should show a normal small delta for the pre-existing articles and an initial bulk load only for the new one.

The SSMS GUI Equivalent

Publication Properties → Articles → check the new table → OK triggers a prompt along the lines of "You have added or removed one or more articles... this action requires the publication to be reinitialized." with options to reinitialize now, later, or skip. Choosing to mark it for reinitialization later (or explicitly declining an immediate reinit, depending on SSMS version) has the GUI issue the same @force_invalidate_snapshot = 1 call under the hood without touching existing subscriptions. Reading that dialog carefully before clicking through it is the entire difference between a five-minute change and an unplanned multi-hour resync.

What Breaks This

Things that force you back onto the full-reinit path:
  • No primary key on the new table. Transactional replication articles need one (or a unique index the Log Reader can use as a row identifier); add it before you call sp_addarticle.
  • Modifying an existing, already-replicating article's schema at the same time. That's a different operation (sp_repladdcolumn/sp_repldropcolumn, or a schema replication change through the article's DDL options), don't fold it into the same maintenance window as adding a brand-new article unless you've tested the combination.
  • Peer-to-peer replication. The same technique generally applies, but peer-to-peer topologies replicate DDL between nodes automatically and have their own sequencing rules; validate the exact behavior on a non-production topology first.
  • Merge replication uses a different mechanism entirely (sp_addmergearticle), and generally does not require reinitializing existing subscribers when you add an article either, but the parameters and agent behavior differ enough that this walkthrough shouldn't be assumed to transfer directly.

Why Not Just Always Reinitialize?

Sometimes you should. Full reinitialization is simpler to reason about and leaves no ambiguity about subscriber state. It's the right call when you're already touching most of the published tables, when the publication is small enough that the cost is trivial, or when subscribers have drifted and you want a clean baseline anyway. The technique in this article is for the specific, common case: the publication is healthy, most tables don't need to move, and you're adding one (or a few) new tables to a pipeline that's already working.

The Verdict

Adding an article to a live publication does not have to mean re-copying everything that's already replicating. Set @force_invalidate_snapshot = 1, leave @force_reinit_subscription at its default of 0, add the subscription for the new article only, and run the Snapshot Agent once. Verify in Replication Monitor that only the new article got an initial bulk load before you close the change ticket.