---
title: "Medium"
description: "Medium is a well-known blog platform, and Medium Engineering is like a blog inside a blog, where you can find articles from the team that builds Medium. You’ll learn about front- and backend issues, problem-solving, and the most interesting and unique Medium technologies. Every once in a while, you’ll find some articles on Medium engineering culture and company values."
---

# Medium
> Medium is a well-known blog platform, and Medium Engineering is like a blog inside a blog, where you can find articles from the team that builds Medium. You’ll learn about front- and backend issues, problem-solving, and the most interesting and unique Medium technologies. Every once in a while, you’ll find some articles on Medium engineering culture and company values.

## Articles

### [How we think about text classification in the LLM era](https://yomu.fyi/post/how-we-think-about-text-classification-in-the-llm-era.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Raphael Montaud
- Published: Aug 19, 2026
- Type: Problem & solution

Medium revisited its aging NSFW text-classification model, which had outdated code, infrequent retraining, and poorly documented training and performance history. The replacement uses an LLM prompt containing NSFW guidelines and story content, requesting a 0-to-100 score, structured output, and a short reason rather than requiring a training set. To evaluate it, the team created a curator-labeled dataset with deliberate oversampling of NSFW stories, then compared several LLMs with the legacy model using false-positive and false-negative metrics. Some models matched or exceeded the legacy model; the team selected Mixtral 8×7b based on cost and performance and ran inference in Snowflake. The post presents this as a strong fit where training data is costly, trends are relatively stable, and only distribution-eligible stories need scoring, while topic and spam models still benefit from continuously updated datasets.


### [How we built the new Table of Contents feature](https://yomu.fyi/post/how-we-built-the-new-table-of-contents-feature.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Scott Batson
- Published: Jul 23, 2026
- Type: Explainer

Medium built a new Table of Contents feature after an existing Chrome extension demonstrated demand, while its approach of inserting a static list into post content created revision, maintenance, navigation, and reading-experience problems. The shipped implementation derives a nested list from the rendered post body at runtime: H2 and H3 become top-level entries, H4 headings nest beneath the latest top-level heading, and lead title, subtitle, and kicker are excluded. It appears as a right-margin indicator that scrolls with the reader, highlights the current heading, supports smooth scrolling, and uses a sliding window for posts with many headings. Full-width images receive a translucent background, one-heading posts hide the feature, and mobile needs a separate solution because desktop indicators overlap content; the feature took a couple of days, mostly for UX testing and design iteration.


### [Outcomes we want to see from AI at Medium Engineering](https://yomu.fyi/post/outcomes-we-want-to-see-from-ai-at-medium-engineering.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Jacob Bennett
- Published: May 26, 2026
- Type: Explainer

Medium Engineering defines desired outcomes and anti-goals for adopting AI, emphasizing leverage, learning, technical ambition, rigorous reasoning, fluency, and maintainable code rather than raw output. Engineers are expected to use AI for repetitive refactoring, testing, unfamiliar systems, design exploration, code analysis, and safer cross-stack work while retaining accountability for clarity, correctness, coverage, and judgment. The guidance rejects PR, commit, line, token, and model-spend metrics as success measures, allowing them only as debugging signals. It also warns against blind trust, unreviewable code volume, loss of codebase understanding, security or privacy regressions, misaligned vendors, environmental hand-waving, and performative tool adoption. The stated north star is achieving outcomes that let Medium’s humans move with the responsiveness of a much larger team while staying true to what makes the platform worth building.


### [How we improved image download sizes on Medium with just four characters](https://yomu.fyi/post/how-we-improved-image-download-sizes-on-medium-with-just-four-characte.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Scott Batson
- Published: May 18, 2026
- Type: Explainer

Image-heavy websites need browsers to choose efficient image variants, but srcset and sizes can require complex breakpoint rules for responsive layouts. The post distinguishes picture, which lets authors prescribe sources based on conditions, from srcset, which gives browsers candidate dimensions and lets them choose using context such as connectivity and cache state. It explains that browsers begin fetching images before layout is rendered, while lazy-loaded images can defer fetching until their dimensions are known. With WebKit's March 24, 2026 support for auto in sizes on lazy-loaded images, the recommendation is to prepend auto to those sizes attributes; unsupported browsers ignore the unparseable rule. On Medium, the change made the home feed's image-related download chunk about 7% smaller on a small, but not mobile-small, display, and the text says WordPress updated every instance broadly.


### [Making AI Write Android Code Our Way: A Practical Guide to Agent Skills](https://yomu.fyi/post/making-ai-write-android-code-our-way-a-practical-guide-to-agent-skills.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Pierrick CAEN
- Published: Mar 17, 2026
- Type: Tutorial

An Android team at Medium describes how it encoded its project conventions so AI assistants generate code aligned with Clean Architecture, Kotlin, Jetpack Compose, Hilt, Apollo GraphQL, and feature modules. An AGENTS.md file provides persistent context about module structure, dependency injection, state management, navigation, testing, and commands, while Markdown skills in .agents/skills/ provide ordered runbooks for specific tasks. Examples cover scaffolding screens and feature modules, migrating Material 2 to Material 3, enforcing ViewModel feature-flag handling, and adding deeplinks, analytics, translations, and tests. Detailed patterns include ViewModel-injecting and @VisibleForTesting composables, assisted injection, StateFlow, Result, MockK, Turbine, and Robolectric. The team iterates skills from review feedback, keeps them version-controlled, and plans file-aware rules plus commands for release diffs and reporting.


### [We’re Hiring a Principal Backend Engineer to Shape the Future of Medium](https://yomu.fyi/post/we-re-hiring-a-principal-backend-engineer-to-shape-the-future-of-mediu.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Michael Margolis
- Published: Oct 22, 2025
- Type: Announcement

Medium is hiring a Principal Backend Engineer, its most senior individual-contributor level, to lead the evolution of backend systems supporting reading, writing, and discovery for millions of users. The role combines hands-on engineering with organizational leadership: the hire will define backend strategy, set quality and architectural standards, review critical designs and code, mentor engineers, and partner with engineering, design, data, and executive leadership. Its technical focus includes modernizing a large living codebase, improving reliability and scalability, and balancing long-term platform evolution with building, debugging, and refining systems directly. Medium says the position should help teams move faster and ship with confidence while keeping the technology fast, stable, and built for longevity; it is fully remote in the US and seeks engineers experienced with systems used by millions, technical debt, fan-outs, and complex edge cases.


### [Medium Android App — Migrating from Apollo Kotlin 3 to 4: Lessons Learned](https://yomu.fyi/post/medium-android-app-migrating-from-apollo-kotlin-3-to-4-lessons-learned.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Pierrick CAEN
- Published: Oct 6, 2025
- Type: Tutorial

Migrating the Medium Android app from Apollo Kotlin 3 to 4 exposed cache and exception-handling issues that were hidden by the earlier implementation. Apollo Kotlin 4 uses a new group, plugin, and package identifier, places exceptions in ApolloResponse, and replaces ApolloCompositeException with a primary exception plus suppressed failures. CacheMissException errors appeared in watch() because programmatic cache IDs were incomplete or incorrect; the app addressed this with declarative type and field policies, \_\_typename on every operation, cache-update helpers, and policy-aware safeWatch filtering. The migration also replaced executeV3(), removed fetchThrows = true, added a Currency scalar adapter, and identified HTTP batching and persisted queries as future improvements, while concluding that Apollo 4 produced a more robust cache integration after the underlying issues were fixed.


### [Engineering stories behind the Medium Daily Digest Algorithm: Part 2](https://yomu.fyi/post/engineering-stories-behind-the-medium-daily-digest-algorithm-part-2.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Raphael Montaud
- Published: Aug 28, 2025
- Type: Problem & solution

Medium’s Daily Digest filtering had become costly and difficult to maintain after a single Bloom Filter instance accumulated billions of items for read, muted, and presentation rules. The system could face up to 15,000 filter questions per feed and more than 15 million per second across thousands of feeds, while Bloom Filters could not delete or enumerate entries and introduced derived-data drift. The team replaced the muted-writer filter with a user-based database query that fetched all muted writers for the current user and cross-referenced them with the story shortlist, then split read filtering between early user-based queries and later pairwise lookups. The resulting implementation removed Bloom Filters entirely, was reported as ten times cheaper in their situation, made costs independent of shortlist size, supported reading-history clearing, and was easier to control and debug.


### [Engineering stories behind the Medium Daily Digest Algorithm: Part 1](https://yomu.fyi/post/engineering-stories-behind-the-medium-daily-digest-algorithm-part-1.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Raphael Montaud
- Published: Aug 26, 2025
- Type: Problem & solution

Medium’s Daily Digest recommendations were less relevant than the homepage despite identical story sourcing, ranking model, and features, because digest filtering operated with less email-reporting information and was too aggressive. The “Sent in Opened Digest” filter excluded all 15 stories after an email-open signal, even when a reader saw only the first five; Apple Mail Privacy Protection also caused servers to preload messages, making many open events unreliable. Medium removed that filter and reduced the backoff from seven to four days, accepting more repetition while relying on other filtering rules and organic recommendation changes to diversify digests. An A/B test found that experiment users were 10% more likely to convert to paying members and read 7% more on Medium. The post says these results led to more filter investigations, including Bloom Filters, “Hard vs Soft Filtering,” and cross-digest diversification, while recommending audits of products that depend on email-open tracking.


### [Engineering stories behind the Medium Daily Digest Algorithm: Part 4](https://yomu.fyi/post/engineering-stories-behind-the-medium-daily-digest-algorithm-part-4.md)
- Company: [Medium](https://yomu.fyi/company/medium.md)
- Author: Raphael Montaud
- Published: Aug 25, 2025
- Type: Problem & solution

Medium’s Daily Digest team investigated complaints that recommendations had become repetitive, especially for power users, after earlier filtering changes. Data showed some stories were sent up to eight times to one user, while affected users saw digest posts repeated twice on average; the team also had to account for Apple Mail Privacy Protection, which prevents reliable open tracking. They therefore tracked digest email IDs when readers clicked a story, marking emails with at least one click as “definitely opened,” and added a recommendation-stack filter that counts prior occurrences in those digests. Testing supported a threshold of one occurrence: complaining users would lose nearly five stories per digest, whereas free users would lose fewer than one. An A/B test produced a statistically significant increase in reading time, with a larger rise among members; the team reported no further complaints and suggested soft filtering and email-position rules as possible refinements.
