ingestion-pipeline-doctor-nodejs
Skill727 starsChanged yesterdayMITView on GitHub
Ingestion pipeline architecture overview and convention reference. Use when you need a quick orientation to the pipeline framework or want to know which doctor agent to use for a specific concern.
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 59
Results: Use ok(), dlq(), drop(), redirect() constructors.
- Distinctive: line 73
Ask Claude to "run all pipeline doctors on my recent changes" to get a comprehensive review across all 4 concern areas.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Pipeline Doctor
Quick reference for PostHog's ingestion pipeline framework and its convention-checking agents.
Architecture overview
The ingestion pipeline processes events through a typed, composable step chain:
Kafka message
→ messageAware()
→ parse headers/body
→ sequentially() for preprocessing
→ filterMap() to enrich context (e.g., team lookup)
→ teamAware()
→ concurrentlyPerGroup(token:distinctId) for per-entity processing
→ gather()
→ pipeChunk() for chunk operations
→ handleIngestionWarnings()
→ handleResults()
→ handleSideEffects()
→ build()See nodejs/src/ingestion/pipelines/analytics/joined-ingestion-pipeline.ts for the real implementation.
Key file locations
| What | Where |
| Step type | nodejs/src/ingestion/framework/steps.ts |
| Result types | nodejs/src/ingestion/framework/results.ts |
| Doc-test chapters | nodejs/src/ingestion/framework/docs/*.test.ts |
| Joined pipeline | nodejs/src/ingestion/pipelines/analytics/joined-ingestion-pipeline.ts |
| Doctor agents | .claude/agents/ingestion/ |
| Test helpers | nodejs/src/ingestion/framework/docs/helpers.ts |
Which agent to use
| Concern | Agent | When to use |
| Step structure | pipeline-step-doctor | Factory pattern, type extension, config injection, naming |
| Result handling | pipeline-result-doctor | ok/dlq/drop/redirect/timeout, side effects, warnings |
| Composition | pipeline-composition-doctor | Builder chain, concurrency, grouping, branching, retries |
| Testing | pipeline-testing-doctor | Test helpers, assertions, fake timers, doc-test style |
Quick convention reference
Steps: Factory function returning a named inner function. Generic <T extends Input> for type extension. No any. Config via closure.
Results: Use ok(), dlq(), drop(), redirect() constructors. Side effects as promises in ok(value, [effects]). Warnings as third parameter. Steps never return timeout(): only the budget checkpoints produce it.
Batch time budgets (feed(elements, batchContext, BatchBudget.softDeadline(softAt))): the framework stops starting steps once a batch's budget runs out, and the cut-off elements complete as timeout(), which is not acked and is redelivered. .timeoutBarrier() marks the last checkpoint: an element past it with time left always finishes. Place it before the first step whose writes make finishing cheaper than redelivering, and before any side effect that is unsafe to repeat, because a cut element is redelivered and its chain runs again from the top. A group that runs one element at a time completes a prefix of its feed order, but concurrently and fan-out/fan-in do not keep that prefix. Details: nodejs/src/ingestion/framework/docs/18-batch-budgets.test.ts.
Composition: messageAware wraps the pipeline. handleResults inside messageAware. handleSideEffects after. concurrentlyPerGroup for per-entity work. gather before chunk steps.
Batching lifecycle hooks (BatchingPipeline beforeBatch/afterBatch): enrich-only. Hooks may enrich elements and batch context but must return exactly the elements they received — a count change is a broken invariant and feed() throws. Filtering belongs in sub-pipeline steps that return drop(). An empty feed() is a no-op (no hooks, no capacity). Details: nodejs/src/ingestion/framework/docs/14-batching.test.ts.
Fan-out/fan-in (fanOut(fn).via((sub) => …).fanIn(fn)): per-element sub-work with cardinality restored — one element fans out to N sub-elements (e.g. per-blob uploads), a regular sub-pipeline processes them (maxConcurrency on the sub concurrently block, retry on the per-sub step), and fan-in folds the OK results back into the parent. Reach for it over concurrently/concurrentlyPerGroup when the unit of concurrency is smaller than the element; hand-rolled p-limit/Promise.all inside a step is the tell. Sequencing is compile-time enforced (an unclosed stage cannot build). Sub-result contract: OK collected; DROP excludes the sub silently; DLQ fails the parent with aggregated reasons; REDIRECT is excluded with a warning — sub redirects never escape the stage; TIMEOUT times the parent out and wins over DLQ. Sub-pipelines are context-agnostic: team/message data goes in the sub-element value, and context-gated surface (teamAware, handleIngestionWarnings, …) is uncallable. Fan-out/fan-in functions are cheap, synchronous, and named. Parents emit unordered as they complete. Details: nodejs/src/ingestion/framework/docs/17-fan-out-fan-in.test.ts.
Testing: Step tests call factory directly. Use consumeAll()/collectChunks() helpers. Fake timers for async. Type guards for result assertions. No any.
Running all doctors
Ask Claude to "run all pipeline doctors on my recent changes" to get a comprehensive review across all 4 concern areas.
Other versions1 project uses a version of this.
Word for word · 1
- PostHog/posthog★ 40k100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository124 other files it gives its agents.
- AGENTS.mdAGENTS.md
- common/AGENTS.mdAGENTS.md
- hog/AGENTS.mdAGENTS.md
- proto/AGENTS.mdAGENTS.md
- rust/AGENTS.mdAGENTS.md
- .cursor/rules/django-python.mdcCursor rule
- .cursor/rules/react-typescript.mdcCursor rule
- .cursor/rules/rust.mdcCursor rule
- adding-activity-loggingSkill
- adding-api-scopesSkill
- adding-inbound-webhooksSkill
- adding-inbox-sourcesSkill
- adding-ingestion-warningsSkill
- adding-mcp-store-serversSkill
- adding-personhog-rpcSkill
- adding-product-alertingSkill
- adding-project-secret-api-key-authSkill
- adding-today-highlightsSkill
- adopting-generated-api-typesSkill
- analyzing-experiment-precompute-canarySkill
- analyzing-experiment-query-performanceSkill
- analyzing-insights-across-teamsSkill
- announcing-behavior-changesSkill
- auditing-llm-gateway-paritySkill
- auditing-warehouse-source-coverageSkill
- authenticating-to-clickhouseSkill
- authoring-ci-workflowsSkill
- building-product-empty-statesSkill
- building-the-toolbarSkill
- clickhouse-migrationsSkill
- debugging-ci-failuresSkill
- debugging-local-replaySkill
- debugging-local-task-agent-runsSkill
- debugging-mcp-analyticsSkill
- debugging-signals-pipelineSkill
- debugging-table-access-deniedSkill
- depot-ciSkill
- depot-container-buildsSkill
- depot-github-runnersSkill
- developing-subscriptionsSkill
- django-migrationsSkill
- django-startup-timeSkill
- documenting-warehouse-sourcesSkill
- editing-agents-mdSkill
- establishing-code-ownershipSkill
- extending-hobby-smoke-testsSkill
- extending-personhog-test-harnessSkill
- finding-llm-gateway-migration-candidatesSkill
- fixing-flaky-testsSkill
- formatting-slack-messagesSkill
- gating-production-deploysSkill
- gating-sensitive-actionsSkill
- generating-clickhouse-query-performance-reportsSkill
- hogliSkill
- implementing-mcp-toolsSkill
- implementing-mcp-ui-appsSkill
- implementing-warehouse-sourcesSkill
- improving-drf-endpointsSkill
- improving-mcp-toolsSkill
- instrumenting-first-party-metricsSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

