Skip to content

blog post: Surgery on a load-bearing assumption#16361

Open
dmarticus wants to merge 4 commits intomasterfrom
dmarticus/blog-idea-review
Open

blog post: Surgery on a load-bearing assumption#16361
dmarticus wants to merge 4 commits intomasterfrom
dmarticus/blog-idea-review

Conversation

@dmarticus
Copy link
Copy Markdown
Contributor

Changes

New engineering blog post: "Surgery on a load-bearing assumption"

An eng blog post about changing a foundational assumption in PostHog's feature flag evaluation engine (that a flag targets exactly one entity type) to support mixed person+group targeting. Structured as a reusable playbook:

  • The stent: adding a new field alongside the old one with a safe fallback (Option<Option<i32>> / effective_aggregation)
  • The staging: constraining first, then relaxing -- shipping the new data model with the old constraint enforced, then lifting it after the evaluator catches up
  • Post-op: hunting for the assumption in places that never referenced the field directly, like a reason-priority scoring function

Checklist

  • I've read the docs and/or content style guides.
  • Words are spelled using American English
  • Use relative URLs for internal links
  • I've checked the pages added or changed in the Vercel preview build
  • If I moved a page, I added a redirect in vercel.json

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 14, 2026

Deploy preview

Status Details Updated (UTC)
🟢 Ready View preview Apr 21, 2026 10:41PM

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 14, 2026

Vale prose linter → found 0 errors, 4 warnings, 0 suggestions in your markdown

Full report → Copy the linter results into an LLM to batch-fix issues.

Linter being weird? Update the rules!

contents/blog/mixed-targeting-feature-flags.md — 0 errors, 4 warnings, 0 suggestions
Line Severity Message Rule
22:43 warning Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. PostHogBase.ProductNames
50:28 warning Capitalize 'Feature Flags' for PostHog's product. Use 'feature flags' for the general industry concept. PostHogBase.ProductNames
72:155 warning 'serde's' is a possible misspelling. PostHogBase.Spelling
72:213 warning 'deserializer' is a possible misspelling. PostHogBase.Spelling

Comment thread contents/blog/mixed-targeting-feature-flags.md Outdated
@@ -0,0 +1,121 @@
---
Copy link
Copy Markdown
Contributor Author

@dmarticus dmarticus Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qq: should I also name this file the same name as the post, e.g.

mv contents/blog/mixed-targeting-feature-flags.md contents/blog/surgery-on-a-load-bearing-assumption.d

?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can go with the title but maybe just: load-bearing-assumption-surgery?

We're not getting any SEO points for any of these so can be just short and close to the title.

Copy link
Copy Markdown
Contributor

@ivanagas ivanagas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Higher level thoughts, can do a more detailed pass after you update

@@ -0,0 +1,121 @@
---
title: "Surgery on a load-bearing assumption"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know people around here hate stuff like this, but:

Suggested change
title: "Surgery on a load-bearing assumption"
title: "How to do surgery on a load-bearing assumption"

As a reader, makes me a bit more curious, I might have load-bearing assumptions I want to do surgery on too.

Copy link
Copy Markdown
Contributor

@jina-yoon jina-yoon Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with "How to" but i think having both "surgery" and "load-bearing" is too many metaphors in one title. more variations -

Suggested change
title: "Surgery on a load-bearing assumption"
title: "How to perform surgery on a live assumption"
Suggested change
title: "Surgery on a load-bearing assumption"
title: "How I performed surgery on a load-bearing assumption"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

title is hard lol i'm not sure about any of these yet either

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind "How I performed surgery on a load-bearing assumption"; I'll make that change.

metaDescription: "How we changed a foundational assumption in PostHog's feature flag engine -- and a playbook for doing it in your own systems."
---

I recently shipped [mixed targeting](/docs/feature-flags/user-and-group-targeting) for [feature flags](/feature-flags) -- letting a single flag target both users and groups at the same time. 15 PRs across four repos. The part I keep thinking about is how hard it was to find all the places the old assumption lived.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this intro, before the json code, we want to:

  1. Make it clear what we're talking about when we say "assumption"
  2. Introduce the surgery analogy

If you are coming into this blog without context, this is unclear. Even after reading the full first section, I get that aggregation_group_type_index some data that groups inherit but I don't fully connect why that's an "assumption" or why you'd do surgery to get rid of it.

If we get this clear, there's not that much more that needs to be done.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried to do a rewrite and restructure of the intro to add all this context - feel free to add further edits!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think there's some issue with whether we are using past tense or present tense, 1st person or 3rd person. I get edit this more closely on next pass, just something to be aware of.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1! i just finished a pass and tried to fix them

@@ -0,0 +1,121 @@
---
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can go with the title but maybe just: load-bearing-assumption-surgery?

We're not getting any SEO points for any of these so can be just short and close to the title.


A three-variant enum would be more readable, but the JSON wire format is already `null` or a number, and `Option<Option<i32>>` maps to that directly with serde's defaults. A custom enum would need a hand-written deserializer to produce the same JSON shape, which is more code for the same result. Ugly, but the path of least resistance when you're keeping an existing API contract intact.

The resolution logic is simple:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what this logic does in like one sentence for us who don't know rust?

Copy link
Copy Markdown
Contributor

@jina-yoon jina-yoon Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 i didn't touch most of the Rust explanations because I couldn't understand them


You can grep for a field name. You can't grep for an assumption.

## The stent
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you like to keep your titles more stylish, but I literally didn't know what a stent was until I read the rest and figured it out, could it be a bit more informative?

Suggested change
## The stent
## Insert the stent


The stent is the most important part of the whole project. It's what makes the rest of the surgery safe.

## The staging
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand what's staged here? What would be the verb we would use with staging?


The whole point is that the last incision is tiny. All the risk was managed in the earlier steps.

## Post-op
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the right way to say this but can we say something like this?

Suggested change
## Post-op
## Fixing new issues in post-op


I found a few more places like this. The blast radius endpoint returned either user counts or group counts, never both. The frontend rendered one unit label per flag. The SDK request payloads assumed one hash key type. None of them referenced the field. All of them depended on the assumption.

In my experience, assumptions tend to hide in three places: **ranking and priority logic** (like the scoring function -- anything that defines an ordering over outcomes), **API response shapes** (like the blast radius endpoint -- anything that assumes a fixed cardinality in its return type), and **UI rendering code** (like the unit labels -- anything that maps data to a display format). If you're doing this kind of surgery, those are the places I'd audit first.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For most readers, this is probably the most useful piece of information, but it's sort of buried here at the end. I'd love something like this at the beginning, even the beginning of the section.

Comment thread contents/blog/mixed-targeting-feature-flags.md
author:
- dylan-martin
featuredImage: >-
https://res.cloudinary.com/dmukukwp6/image/upload/580944574_1ff3a5f8_0cc0_4a25_8ba5_7e532793c1fb_0b30cb5f50.jpg
Copy link
Copy Markdown
Contributor

@jina-yoon jina-yoon Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to the doctor hogs image, so cute

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd die for Dr. Hog


This stent was the most important part of the whole project. It's what makes the rest of the surgery safe and possible.

## Part 2: Staging
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to ian's comment earlier - something parallel to "Placing the stent" would be ideal here for staging

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I was trying to use "staging" to continue the surgery metaphor, but I'm fine to change it up here.


- The blast radius endpoint returned either user counts or group counts, never both.
- The frontend rendered one unit label per flag.
- The SDK request payloads assumed one hash key type.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these three bullets were not clear to me - could you flesh them out?

that way also they're not identical in format to the final bulleted list in the Lessons learned section.

2. **API response shapes** like the blast radius endpoint – anything that assumes a fixed cardinality in its return type
3. **UI rendering code** like the unit labels – anything that maps data to a display format.

For anyone else out there doing this kind of surgery, those are the places I'd audit first. No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to ian's earlier comment - a bit more detail or reflection would be good to wrap up this blog post.

based on how we flesh out stuff in the previous section, i might agree that it would be best to bump these "lessons learned" to the beginning for anyone who wants to get the advice without reading the full story

@dmarticus
Copy link
Copy Markdown
Contributor Author

@jina-yoon @ivanagas y'all are the best – thanks for the feedback! I'll wrap this up today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants