Last updated: October 21, 2026

Quick Answer: backfill old content into WordPress without duplicates by importing a fixed date window, checking each source item against existing post slugs or source IDs before insert, and refusing to publish anything that already has a record in the database.

Key Takeaways

  • Set a source list, a stable identity rule, and a reject-staging place before changing import settings.
  • Import in order, check each source item before insertion, and skip or update only matching records.
  • Keep the source published date, one stable slug, and the canonical URL on the final WordPress post.
  • Check wp_posts, then source-ID metadata, then the slug.

If the goal is content backfilling on an auto blog, the real problem is not getting old posts into WordPress once. The real problem is getting them in once only, with the right published dates, canonical URLs, categories, and status so the archive does not split into twins. That means treating backfill runs like database work, not like a loose copy-and-paste job; if the workflow is complex, consult a WordPress professional or developer and follow the WordPress Codex guidance on imports and data handling.

What you need before the first backfill run

You need three things before you touch import settings: a source list, a stable identity rule, and a place to stage rejects. The source list can be an RSS feed, a CSV export, or another feed-compatible source that includes at least a title, published date, and URL. The identity rule is the field you will use to decide whether a post already exists in WordPress, usually the source GUID, source URL, or a normalized post slug. The staging place can be a draft status, a separate category such as import-review, or a log file outside WordPress.

For a clean historical import, define your import window before the first run. For example, decide whether you are backfilling the last 90 days, a full year, or only items before a cutoff date like 2024-01-01. Without that boundary, you end up reprocessing items forever and the duplicate check becomes noisy.

You also need access to the WordPress database or at least an importer that can query it. A duplicate-prevention rule only works if it can check existing post records in wp_posts and, when needed, related metadata in wp_postmeta. If you cannot query those records, you are guessing.

This is also the point to decide what should happen when the source already has a post that WordPress contains. The safe default is skip. A second safe option is update the existing record only if the source item carries the same external ID. What you should not do is create a new post every time the feed republishes an older story with a new timestamp.

How do you backfill old content into a WordPress auto blog without creating duplicates?

You backfill old content by importing in order, checking each source item against existing posts before insertion, and stopping any record that matches by source ID, canonical URL, or slug. That is the core of duplicate prevention.

Use this order for the run:

  1. Set the import window, such as items published before `2025-01-01` or between two dates like `2024-06-01` and `2024-12-31`. The result should be a finite queue, not an endless feed.
  2. Normalize the source item into one identity key. A common choice is the feed GUID; if that is missing, use the source URL; if that is unstable, fall back to a slug made from title plus date.
  3. Query WordPress for that identity before creating anything. Check `wp_posts.post_name` for slug matches and, if your importer stores it, check `wp_postmeta` for the source ID. When the check works, you will find either one match or none, never both by accident.
  4. If a match exists, skip the item or update the same record. The expected result is zero duplicate inserts and a log entry that says why the item was skipped.
  5. If no match exists, insert the post with the source published date, not the import date. The archive should place the post where the original date belongs, and the WordPress month archive should reflect that date.
  6. Assign taxonomy only after the identity check passes. Categories, tags, and featured images belong on the accepted record, not on a duplicate that might be deleted later.
  7. Run the same import a second time against the same 10 to 20 test items. A correct backfill produces no second copy, no second slug, and no new published record for those same items.

The main mistake here is checking only the title. Titles repeat often enough that a title-only filter will miss duplicates and sometimes block legitimate posts with similar names. Slug matching is better, but only if the slug is normalized consistently. A title like “Market Update: Q4” can become different slugs depending on punctuation, stop words, or date suffixes.

For feed-based imports, store the source GUID or feed item URL in post meta. That gives you a direct lookup key and avoids fragile title comparisons. If your tool cannot store metadata, use a custom field named something like source_url or source_guid. A backfill that cannot identify its own source is one cron run away from a duplicate archive.

How to handle published dates, slugs, and canonical URLs

You should preserve the original published date, generate one stable slug, and point the canonical URL at the final WordPress post. Those three choices keep the archive readable and keep search engines from seeing a backfilled post as a new copy of an old one.

The published date matters because WordPress uses it for archive pages, RSS order, and many theme loops. If you import an item from 2023 but stamp it with today’s date, the archive becomes misleading and the content may surface in the wrong place. In a historical import, the source date should usually be the post date in WordPress, while the import timestamp stays in metadata or the log.

Slug handling is where many duplicates begin. If two items share a similar title, a sloppy importer may create my-story, then my-story-2, then my-story-3. That is a symptom of missing identity checks. A better approach is to match the existing post before slug generation. If the post already exists, leave the slug alone. If it does not, create the slug once and keep it stable.

Canonical tags help when a source article and the WordPress copy can both be reached publicly. The canonical URL on the WordPress post should usually point to the WordPress version if the import is intended to become the main record. If the source remains the primary publisher and WordPress is only mirroring excerpts, the canonical decision is different. That choice belongs to your publishing policy, not to the importer by accident.

This is where your SEO settings plugin may matter, but the rule is simple: one post, one canonical URL, one public record. If the same item appears under two URLs with two different slugs and no canonical tag, you have created two indexable versions of one article. That is not backfilling; that is duplication with extra steps.

For guidance on canonical tags and duplicate handling, the Google Search Central documentation on canonicalization is a useful reference, and Yoast’s documentation on canonical URLs is a practical WordPress-specific companion.

What to check in the database before each insert

You should check wp_posts, then any source-ID metadata, then the slug, in that order. That sequence catches the common duplicates without turning every import into a full-table scan.

A practical duplicate-prevention query needs to answer three questions:

  1. Does a post with this external source ID already exist?
  2. Does a post with this normalized slug already exist?
  3. Is there an existing record with the same title and published date that should be reviewed manually?

The first check is the strongest. If you store the source GUID in wp_postmeta, you can query that field directly and avoid guessing. The second check is the fallback when the source ID is absent or unreliable. The third check is a safety net for messy feeds that reuse titles and dates.

If you are using a plugin or custom importer, make sure it checks post_status too. A draft or trash record may or may not count as a duplicate depending on your workflow. For a strict backfill, a draft with the same source ID should usually block a new insert. For a review-driven workflow, that same record might be updated instead. Decide once and apply the rule consistently.

The point of a database check is not just to prevent duplicates from publishing. It is also to prevent duplicate work. If the item already exists, the importer should stop before downloading images, generating excerpts, or assigning categories. That saves time and reduces clutter in logs.

A useful implementation detail is a hash of the source item, such as a checksum over source URL plus title plus date. A hash is not a substitute for a real source ID, but it can help detect a changed feed item during a later run. If the hash changes but the source ID stays the same, you know the source updated its record instead of creating a new one.

How to run historical imports in safe batches

You should run historical imports in small batches, usually 20 to 100 items at a time, so a bad mapping does not contaminate the whole archive. Smaller runs make duplicate checks easier to inspect and rollback.

A batch should cover one time slice, such as one week or one month, not a random mix of years. That keeps the import window predictable. If something goes wrong, you only need to review a narrow date range instead of untangling hundreds of records.

Use a dry run first if your tool supports it. A dry run should show how many items would be inserted, skipped, or updated without writing new posts. If the dry run says 50 inserts and the second dry run says 0 inserts for the same input, your duplicate check is working. If the second dry run still wants to create posts, the matching rule is broken.

Keep a simple log for each batch with four fields: source ID, target slug, action taken, and reason. Even a plain CSV is enough. That log can be the quickest way to answer, “Did this old item already go in?” without clicking through the WordPress admin one post at a time.

Do not change your matching rule halfway through a backfill. If the first batch uses source GUIDs and the second batch uses titles, you will create inconsistent records. If the source feed changes format, pause and map the new fields before continuing.

This is also the right place to connect the backfill job to the larger automated blog publishing workflow. The backfill should behave like one controlled stage inside that pipeline, not like a one-off exception that ignores the same identity rules the live feed uses.

Common duplicate traps during backfill

The most common trap is reimporting the same feed item after a feed refresh, which creates a second post when the title and content look unchanged but the GUID handling is weak. The fix is to key on a persistent source ID, not on the latest feed timestamp.

A second trap is date-based duplication. If the importer treats the import date as the published date, the same historical item can appear new every time you rerun the job. The cost is messy archives and repeated post inserts. The fix is to preserve the source date and separate it from the import timestamp; if the mapping is unclear, consult a WordPress developer or SEO specialist and follow Google Search Central’s duplicate-content guidance.

A third trap is category duplication. If your importer creates a new category when it cannot find an exact name match, “News” becomes “news,” “News ”, or “NEWS,” and the archive splits across near-identical terms. Standardize category lookup before import and create new categories only when they are truly new.

A fourth trap is slug drift. If one run trims punctuation and another keeps it, the same post can end up as two different URLs. The cost is duplicate crawl paths and broken internal references. The fix is to normalize slugs once and refuse to generate a new slug when a source match already exists.

A fifth trap is updating the wrong record. If the importer matches on title alone, it may overwrite a different post with a similar headline. That is worse than a duplicate because it destroys the original. A better rule is to prefer source ID, then URL, then slug, and keep manual review for ambiguous matches.

When to skip a post instead of forcing it in

You should skip a post when the source identity is unclear, the slug already belongs to a different post, or the feed item has been republished in a way that breaks your matching rule. Forcing uncertain items into WordPress is how duplicate archives start.

Skip also makes sense when the item would collide with a post that is already edited in WordPress. If the backfilled version would overwrite a live editorial change, the safer path is to leave the existing record alone and log the source item for review. That is especially important when a backfill reaches older content that has already been improved manually.

A skip is not a failure if the reason is recorded. A good log entry says why the item was excluded, which field caused the match, and whether the item can be reviewed later. Without that record, skipped items vanish into silence and someone reruns the import to “fix” them, which often creates the exact duplicate the skip was meant to prevent.

The right rule is simple: when identity is certain, insert once; when identity is already present, update only that same record; when identity is unclear, stop and skip. That rule is stricter than many auto-blog setups, but it is the one that keeps a WordPress archive clean after the third backfill, not just the first.

How do you import older posts into wordpress without duplicates?

Import older posts into WordPress by loading them in a fixed date range, preserving the source published date, and checking each item against existing posts before creating a new record. The safest method is to match on a source GUID or source URL, then fall back to slug matching if needed. If the item already exists, skip it or update the same record.

How do you avoid reposting the same item during backfill?

Avoid reposting the same item during backfill by storing a permanent external ID and checking it on every run. If the importer cannot store that ID, use a normalized slug plus a source URL lookup as a fallback. The same item should resolve to the same WordPress record, even if the feed is refreshed or reordered.

Can you import only missing posts?

Yes, you can import only missing posts if your importer supports an existence check before insert. The check should compare the source ID, then the canonical URL or slug, and skip anything already present in wp_posts or wp_postmeta. That is the cleanest way to backfill an archive without creating duplicate entries or duplicate slugs.

Drafted with AI; not yet reviewed by a person.