Leaving a note here, because it might be a bit before this is fixable & I don't want to forget about it.
There's a table in a database somewhere called NetworkPosts. This table holds metadata on every post on every site across the entire network. It's used for things that have to combine activity across all sites, such as the Hot Network Questions - and of course, your network profile.
This table gets populated and updated every time something makes relevant changes to a post, whether that's someone editing a title or the post getting closed or a change to the ID of the user who owns it. Every time one of those changes happen, on any site, an event is generated, enqueued in Redis, and eventually processed by the aggregator. Yes, that Aggregator.
When the aggregator processes an event, it runs a bit of code that performs the necessary updates. For example, if a title changes, it runs:
Update NetworkPosts Set Title = @Title Where SiteId = @SiteId And PostId = @PostId
Or if a user is deleted, it runs:
UPDATE NetworkPosts SET OwnerUserId = NULL WHERE SiteId = @SiteId AND OwnerUserId = @UserId
Or if a user is merged, it runs:
Update NetworkPosts Set OwnerUserId = @NewUserId Where SiteId = @SiteId And OwnerUserId = @UserId
The aggregator pulls events from the queue last-in first-out, stopping to process them when it has a healthy number of events - let's say, 20 of 'em. It sorts the events in that batch according to the order in which they were raised, and then runs the associated SQL to actually propagate the changes. Then it goes back to sucking in events from the queue.
Now, here's where things go wrong: merging a user generates a tidy pile of events.
- The reputation of the users involved is changing - gotta propagate those changes
- The merge itself is happening, which affects the aggregated users & posts & such. Gotta raise an event for that!
- Once all their stuff gets moved over to the target user, the source user gets deleted - that's gotta get propagated too, or you'd still have a shell of the old user hanging around somewhere!
Plus, of course, the world doesn't stop every time a user gets merged; folks are still editing titles, and deleting posts, and creating new posts, and doing their own merges and so on. All that goes into the event queue as well.
...That LIFO queue. Which the aggregator is calmly sipping from the top of. Eventually, the aggregator manages to grab that "user deleted" event from the top of the queue without also grabbing the "user merged" event. Not realizing that there's a related merge to process, the aggregator happily processes the deletion... Which removes ownership from all the posts formerly owned by the source user (in the aggregated NetworkPosts table, not on the site where the posts actually live). When the merge event gets processed in the next batch, there are no posts remaining attributed to the source user - so nothing happens.
Well, obviously this has been happening for years... Your merge happened back in 2015!
So, unsurprisingly, there are a few hundred thousand posts without their proper owners floating around the network. Fortunately, this only matters for network profiles - it doesn't actually affect the ownership of the post where it matters: on the site.
Still, it's hardly ideal.
The proper fix here is... To process events in the order they're raised. Fortunately, Redis supports FIFO queues too, so this can happen - and in fact, our intrepid Architecture Team already had this on their TODO list. Not gonna happen overnight, but rest assured it will happen.
Once that's done, we can backfill the proper ownership data and your network profile will once again reflect your actual activity.
Big thanks for taking the time to report this!