PATTERN Cited by 4 sources
Upstream contribution parallel to in-house integration¶
Pattern¶
When you need a new capability that doesn't exist in an upstream open-source project, and you cannot afford to wait on the upstream maintainer's merge timeline, run two paths in parallel:
- Open-source PR path. Build the capability following existing project conventions (architecture, configuration, docs, test patterns) so it can be merged upstream on its merits. Engage the maintainers early; iterate on their feedback.
- In-house integration path. Use the same code — built for upstream — locally in a fork or side-car integration so the internal consumer can ship to production immediately, before the upstream PR merges.
When the upstream PR merges, the in-house integration becomes a thin veneer over the now-upstream code path; the fork collapses into the mainline and maintenance cost drops.
Canonical wiki instance¶
Slack's 2026-03-31 post canonicalises this at the Prometheus Blackbox Exporter × HTTP/3 altitude. Intern Sebastian Feliciano both open-sourced QUIC support into BBE upstream and architected an in-house integration using the new upstream features so Slack could probe HTTP/3 edge endpoints without waiting for merge. Verbatim:
"Making an open-source contribution as an intern is a huge accomplishment. As many of us know, maintainers don't always merge PRs quickly, especially for new features. Sebastian's internship timeline was limited, so he couldn't wait. Sebastian took matters into his own hands and architected an in-house system that utilized the new upstream features for probing out HTTP/3 endpoints."
(Source: sources/2026-03-31-slack-from-custom-to-open-scalable-network-probing-and-http3-readiness)
Forces¶
- Maintainer merge timelines are unpredictable. Mature OSS projects with responsible maintainers can take weeks to months to merge new features, especially ones with new dependency surface (Slack's PR pulled in systems/quic-go). The contributor cannot dictate the timeline.
- Internal consumer has a hard deadline. An internship is a hard deadline; a transport migration (HTTP/3 rollout) is a hard deadline; a compliance deadline is a hard deadline. These cannot wait on a merge.
- Fork-and-carry is expensive long-term. Carrying a private fork of a live upstream project generates ongoing rebase cost, drift risk, and duplicate code. You want the fork to collapse into upstream as soon as possible.
- Composability-with-existing-shape earns merge. An upstream PR written "for us" with a bespoke config API won't merge; a PR written to fit the existing project's architecture will. Slack's post explicitly calls out: "had to add this new logic while following the Blackbox Exporter's existing architecture, ensuring the new features maintained the tool's configuration patterns."
Solution shape¶
- Write the new capability for upstream first. Follow the project's config schema, code style, test patterns, docs conventions.
- Open the PR. Engage the maintainers. Respond to feedback, iterate. The PR is the gold copy.
- Track your PR branch as the source of truth internally. Internal integration consumes that branch (as a vendored dependency, as a Go module replace-directive, as a forked repo you rebase onto upstream regularly).
- Ship internal consumer off the PR branch. Don't wait for merge.
- When PR merges: drop the fork. Your internal integration now tracks upstream main directly. Maintenance collapses.
Distinct from related patterns¶
- patterns/upstream-the-fix — that pattern is about contributing fixes to existing features when your scale exposes bugs smaller adopters don't hit. It doesn't speak to the merge-timing problem directly; it's about the choice to contribute at all. This pattern is specifically about how to decouple your ship date from upstream's merge date.
- "Carry a private fork" — the anti-pattern. Forks that never collapse into upstream accumulate maintenance cost forever. This pattern is temporary fork during merge window, not permanent fork forever.
- "Wait for upstream" — the other anti-pattern. You miss your deadline; the feature arrives months late; the internal consumer works around the missing capability in a way that's worse than the temporary fork would have been.
When to use¶
- You are contributing a new feature (not a bug fix) to an upstream OSS project.
- The maintainer timeline for merging new features is weeks to months and outside your control.
- You have a hard internal deadline (internship, migration, compliance, rollout gate) that cannot slip.
- You can write the feature in a form the maintainers will accept — same config shape, same test patterns, same docs.
- The feature's dependency footprint is acceptable to upstream (e.g. systems/quic-go for a QUIC probe is a reasonable dependency for BBE to take on).
When not to use¶
- The feature is company-specific and won't be accepted upstream. In that case keep it as an internal extension and don't open a PR — or contribute a generic extension-point / plugin API to upstream instead, and build your specific feature on top of it downstream.
- The upstream maintainer is inactive or the project is stalled. Fork permanently; contribute to the community successor if one appears.
- The feature requires invasive refactoring of upstream that the maintainer won't accept. Either redesign the feature to be additive, or keep it as a patch you never upstream.
Operational numbers¶
Slack's 2026-03-31 post doesn't disclose how long the upstream
PR took to merge, how long the in-house fork ran before
collapsing, or how much maintenance the fork cost. The pinned
BBE config doc ref — bee8e9102a106bff63281ee9c64c7b1275ef21d0 —
indicates the feature did eventually land upstream. Future
ingests may quantify the fork duration.
Composes with¶
- observability-before-migration — when the capability you need upstream is an observability extension, running the PR-and-integration in parallel lets you close the observability gap on your migration's timeline, not upstream's.
- patterns/upstream-the-fix — the broader "contribute back" pattern this sits within.
- http-3 — the specific gap Slack's BBE contribution closed.
Seen in¶
- sources/2026-03-31-slack-from-custom-to-open-scalable-network-probing-and-http3-readiness — canonical instance. Intern Sebastian Feliciano runs upstream PR + in-house BBE integration in parallel to ship HTTP/3 probing to Slack production on the internship timeline.
- sources/2025-04-15-yelp-journey-to-zero-trust-access — Yelp's corporate-ZTA instance. "Multiple changes have been pushed upstream to Netbird's main branch from Yelpers working to solve issues we encountered, debugged, and ultimately solved." Contribution count not disclosed; the pattern coexists with open-source-for-security-response-agency as two named OSS levers in the selection rationale.
- sources/2026-09-21-cloudflare-python-workers-are-now-generally-available —
Cloudflare's Python Workers GA is a standards-scale instance. Instead of
building Wasm packages usable only in Python Workers, Cloudflare "wanted the
ecosystem to evolve in a way that benefits Pyodide and the
entire Python-on-WebAssembly community": it proposed and landed
PEP 783 / PyEmscripten, stabilized the
Pyodide build toolchain, and added PyEmscripten support to
cibuildwheel— all upstream — in parallel with shipping its in-house Python Workers runtime. It also contributed HTTP-clientfetch-routing upstream soopenai/langchain/mcpwork in Wasm broadly, not just on Workers. - sources/2026-09-28-cloudflare-supporting-native-rust-in-workers-with-the-new-emscripten-target —
second Cloudflare instance, at the Rust-runtime altitude. To run native Rust /
Tokio on Workers via the
Emscripten
wasm32-unknown-emscriptentarget, Cloudflare ran both paths in parallel: upstream — full Tokio support patchsets (the firstwasm32-unknown-emscriptentarget patch already landed in Tokio), trivialtarget_os = "emscripten"gate patches tolibc/socket2/ Mio, and 40+ PRs to Emscripten for the-sNODERAWSOCKETSsocket layer + the-sWASM_BINDGENcooperation with wasm-bindgen — while in-house, the Rust Workers Tokio examples "require these patches directly pending further integration upstream." The temporary-fork-during-merge-window shape: examples ship on the PR branches today, collapse to upstream once the Tokio patchsets merge. "Finalizing the design and upstreaming it is ongoing in collaboration with the Tokio and Emscripten teams."
Related¶
- systems/prometheus-blackbox-exporter — the upstream project.
- systems/quic-go — the dependency the upstream PR pulled in.
- systems/netbird — the Yelp-instance upstream project.
- systems/pyodide — the Python-on-Wasm project Cloudflare upstreamed PEP 783 into.
- systems/emscripten — toolchain basis of the PyEmscripten standard; also the
wasm32-unknown-emscriptentarget +-sNODERAWSOCKETSlayer. - systems/tokio — the Rust runtime whose Emscripten-target support Cloudflare upstreamed while shipping the in-house Rust Workers examples.
- systems/wasm-bindgen — cooperates with Emscripten under
-sWASM_BINDGEN; co-maintained by Cloudflare. - http-3 — the capability gap.
- observability-before-migration — the discipline that made closing the gap a rollout gate.
- patterns/upstream-the-fix — sibling pattern at the fix-existing-feature altitude.
- open-source-for-security-response-agency — the complementary "we can fork if needed" OSS lever.
- companies/slack — BBE adopter.
- companies/yelp — Netbird adopter.