惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
S
SegmentFault 最新的问题
The Last Watchdog
The Last Watchdog
人人都是产品经理
人人都是产品经理
C
Check Point Blog
O
OpenAI News
V
Visual Studio Blog
S
Security @ Cisco Blogs
I
InfoQ
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Troy Hunt's Blog
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
Attack and Defense Labs
Attack and Defense Labs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
SecWiki News
SecWiki News
月光博客
月光博客
U
Unit 42
博客园 - Franky
V2EX - 技术
V2EX - 技术
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
腾讯CDC
量子位
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
N
News and Events Feed by Topic
Engineering at Meta
Engineering at Meta
PCI Perspectives
PCI Perspectives
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
TaoSecurity Blog
TaoSecurity Blog
Project Zero
Project Zero
WordPress大学
WordPress大学
A
Arctic Wolf
H
Help Net Security
Blog — PlanetScale
Blog — PlanetScale
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
I
Intezer
雷峰网
雷峰网
Security Latest
Security Latest
N
News and Events Feed by Topic
AI
AI
V
Vulnerabilities – Threatpost
S
Schneier on Security
Vercel News
Vercel News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Idempotency in Data Pipelines: How to Prevent Duplicate Records
137Foundry · 2026-05-08 · via DEV Community

A pipeline that runs twice should produce the same result as one that runs once. That property is idempotency, and its absence is one of the most common sources of silent data corruption in integration systems. A partially completed run gets retried, the retry reprocesses records that already loaded, and the destination ends up with duplicates that neither the source system nor any monitoring alert ever surfaced.

Designing for idempotency is not complex, but it requires making explicit decisions about state management that are easy to skip when building the initial pipeline.

What Idempotency Means in Data Integration

An idempotent operation produces the same effect when applied once or multiple times. In data integration terms, this means:

  • Inserting the same record twice produces one record, not two
  • Running a pipeline over the same time window twice produces the same output as running it once
  • Retrying a failed partial run does not create duplicates for the records that already loaded

The opposite is a non-idempotent pipeline: every execution adds records, so duplicate runs produce duplicate data. Most pipelines start as non-idempotent because insert operations are simpler to implement than upsert operations, and the duplicate problem only becomes visible after a retry event occurs.

Common Sources of Duplicate Records

Pipeline retries after partial success. A run processes 8,000 of 10,000 records successfully, then fails. The retry starts from the beginning and reprocesses the 8,000 records that already loaded. Without idempotency, these 8,000 records now exist twice.

Parallel execution without coordination. Two instances of the same pipeline run simultaneously, both extracting from the same source window and loading to the same destination. This happens more often than expected with cloud schedulers that retry hung jobs while the original is still running.

Checkpoint failures. A pipeline tracks its progress with checkpoints (offsets, cursors, timestamps). If the checkpoint is written after loading but before the success acknowledgment, a crash between the load and the checkpoint write causes the load to be repeated on the next run.

Upsert as the Foundation of Idempotency

The most reliable approach to idempotency at the storage layer is the upsert operation: insert the record if it does not exist, update it if it does. In SQL terms, this is typically INSERT ... ON CONFLICT DO UPDATE (PostgreSQL) or MERGE (SQL Server, Oracle).

For PostgreSQL, the pattern looks like:

INSERT INTO events (event_id, payload, processed_at)
VALUES ($1, $2, $3)
ON CONFLICT (event_id) DO UPDATE
SET payload = EXCLUDED.payload,
    processed_at = EXCLUDED.processed_at;

Enter fullscreen mode Exit fullscreen mode

The event_id column is the natural key that identifies whether a record already exists. For this to work reliably, every record must have a stable unique identifier that is consistent across extraction runs. If the source does not provide one, you must generate one deterministically from the record's content.

Deterministic ID Generation

When source records do not include a stable unique identifier, you can generate one by hashing the record's identifying fields:

import hashlib
import json

def generate_record_id(record, key_fields):
    """Generate a stable ID from record content."""
    key_data = {field: record[field] for field in key_fields}
    canonical = json.dumps(key_data, sort_keys=True)
    return hashlib.sha256(canonical.encode()).hexdigest()

Enter fullscreen mode Exit fullscreen mode

This approach produces the same ID for the same input data, allowing upserts to detect duplicates even when the source does not provide a unique key. The fields used for hashing must be stable (not timestamps or auto-incremented values) and must uniquely identify the record within the source system.

Time Window Idempotency

For pipelines that extract data by time window, idempotency requires that reprocessing the same window produces the same result. Two approaches work:

Truncate and reload. Before loading data for a time window, delete all existing records for that window and reload from scratch. This is simple and reliable but requires the destination to support deletions and may not work if other processes are writing to the same table concurrently.

Upsert with timestamp tracking. Keep the upsert approach but track which time windows have been fully processed. On retry, skip windows that are marked complete and reprocess only windows that failed mid-run. The Kafka documentation covers offset management patterns that implement this for stream-based pipelines.

Monitoring for Duplicate Records

Even with idempotency in place, monitoring for duplicates provides a safety net:

  • Count distinct records at source and at destination for the same time window. A destination count higher than the source count (allowing for fan-out) indicates duplicates.
  • Check cardinality of the natural key at the destination. Any key value with count greater than one is a duplicate.
  • Alert when the destination record count for a time window increases between run N and run N+1 without a corresponding increase in the source count.

These checks can be run as part of the reconciliation job described in the guide on monitoring data integration pipelines in production.

HTTP Idempotency for API-Based Pipelines

For pipelines that write to destination systems via API, HTTP idempotency keys are the equivalent mechanism. Many modern APIs accept an idempotency key header that causes the server to de-duplicate requests with the same key. The HTTP RFC 7231 defines idempotency at the HTTP method level, and many API providers extend this with explicit idempotency keys.

Submit the same idempotency key with the same payload, and the API returns the previous result without re-processing. This protects against retries caused by network timeouts where the original request succeeded but the response was lost.

Data center infrastructure for pipeline reliability
Photo by Bùi Hoàng Long on Pexels

Testing Idempotency in Pipeline Code

Idempotency is a property that is difficult to verify by inspection. The only way to confirm a pipeline is truly idempotent is to run it twice against the same input and compare the outputs.

The test structure is straightforward:

  1. Run the pipeline once against a known test dataset.
  2. Capture the destination state: record count, contents of key records, and any generated IDs.
  3. Run the pipeline again against the same dataset without clearing the destination.
  4. Assert that the destination state is identical to what was captured in step 2.

For upsert-based pipelines, the destination record count must not increase on the second run, and the content of each record must match the first run's output.

def test_pipeline_is_idempotent(test_dataset, pipeline, destination):
    # First run
    pipeline.run(test_dataset)
    state_after_first_run = destination.snapshot()
    count_first = len(state_after_first_run)

    # Second run with same input, destination not cleared
    pipeline.run(test_dataset)
    state_after_second_run = destination.snapshot()
    count_second = len(state_after_second_run)

    assert count_first == count_second, (
        f"Duplicate records created: {count_second - count_first}"
    )
    assert state_after_first_run == state_after_second_run

Enter fullscreen mode Exit fullscreen mode

For time-window-based pipelines, the test should cover reprocessing an overlapping window: run for window [T1, T2], then run again for [T0, T2] where T0 is before T1. Records in the T1-T2 overlap should not be duplicated after the second run.

Testing idempotency during development is significantly cheaper than discovering and remediating duplicate data in production. A deduplication job on a production table with tens of millions of records is a multi-hour operation that disrupts normal pipeline runs and may still leave edge cases unresolved if the duplicate detection logic is not precise.

Idempotency as a Design Constraint, Not a Fix

The most important thing about idempotency is that it needs to be designed in from the start. Adding idempotency to an existing non-idempotent pipeline that has been running in production requires auditing the destination for existing duplicates, migrating the storage layer to support upserts, and potentially deduplicating historical data. That is a significant effort compared to building with upserts from day one.

137Foundry builds data integration pipelines with reliability properties including idempotency, dead letter queues, and schema change detection built in. The data integration service and the broader services hub describe the full scope of what we work on.