24 Aug 2026
Django community aggregator: Community blog posts
Django Developers Survey 2026
🔗 Links
- 2026 Django Developers Survey Results
- Django 6.1 release notes
- Talk Python #446: Updates on Django's Async Story with Carlton
- Choose Boring Technology
🎥 YouTube
24 Aug 2026 5:32pm GMT
Planet Python
Django Weblog: The Block and Tackle of Django's Code of Conduct Working Group
In early 2026, Django's Code of Conduct Working Group adopted Contributor Covenant 3.0 as Django's Code of Conduct. I talked about why at DjangoCon US 2026 (slides here). That talk was mostly the story of how we managed the people side of the process. This post is the technical mechanics of how we managed the change and our work going forward.
Who can change what, and who has to sign off
The Code of Conduct Working Group is established by the DSF board and kept deliberately small. At least three people, per the working group manual, recruited for diversity of geography, background, and lived experience rather than just availability. Membership is volunteer and term-limited. Terms became annual in February 2026, and if a member doesn't respond to the January renewal check-in within a week, they're rolled off. Nobody has to feel guilty about stepping back.
The board isn't a separate, distant approval layer sitting above the working group. The DSF board's president always holds a seat on the working group and acts as its board liaison. Other board members can volunteer alongside them, and two currently do, in addition to the chair. Day to day, the working group operates independently. It only has to go back to the board for three things: spending money, taking a drastic punitive action, or altering the Code of Conduct text itself.
There's a second working group in the mix too. The Online Community Working Group handles routine moderation of Django's day-to-day spaces. It doesn't touch the Code of Conduct Working Group at all until something gets escalated: a formal report, a violation spanning multiple spaces, or an issue neither group can resolve alone. Each group appoints one of its own members as liaison to the other. If the two groups can't reach consensus on something that needs joint handling, either chair can send it to the board.
Inside the working group itself, decisions are made by consensus first. If that doesn't happen, a two-thirds majority of members without a conflict of interest can decide instead. If neither happens in a reasonable timeframe, it goes to the board.
The process for changing the process
Before anyone touched the Code of Conduct's actual text, the working group created a process for how changes get proposed at all. Issue #69, opened January 13, 2026, asked for exactly that. PR #70 answered it the same day by adding updates.md and a structured issue template for proposals.
The rules are plain. Anyone in the Django community can propose a change by opening an issue against that template. It asks what's changing, why, and whether it touches the CoC text itself or just supporting documentation. The working group can skip the full process for genuinely minor edits, things like typos, membership list updates, or FAQ tweaks. Everything else gets discussed at the working group's regular monthly meeting, with input from the wider community pulled in through the forum, Discord, or DSF Slack when a change is significant enough to warrant it.
Approval splits along the same line as the board relationship above. The working group can merge changes to supporting documentation on its own consensus. A change to CODE_OF_CONDUCT.md itself needs the board's sign-off first. That split isn't just written policy, it's enforced mechanically by a two-line CODEOWNERS file:
* @django/coc-committee
CODE_OF_CONDUCT.md @django/coc-committee @django/dsf-board
Every file in the repo requires the working group's review. CODE_OF_CONDUCT.md additionally requires the board's. GitHub won't merge a PR touching that one file without both. If you're setting up something similar, this is worth copying directly: two lines, and your governance policy becomes something GitHub enforces instead of something people are trusted to remember.
Additionally, we require a 30-day public comment period for all PRs that aren't administrative (fixing typos, updating membership lists, changelog updates, etc.). The working group can merge a PR after 30 days even if nobody comments, but if anyone does, the discussion has to be resolved before merging. This is the mechanism that makes the process public and transparent. It doesn't require anyone to read every comment, but it does require the working group to respond to them. You can use our workflow to enforce that for your project as well. There's two settings BYPASS_LABEL and MIN_AGE_DAYS to tweak the behavior, but the defaults are a 30-day wait and an expedited label that lets the working group skip it for administrative changes.
Once something merges, it gets announced on the blog, forum, social, whatever's appropriate for the size of the change, with a summary, the rationale, and links to what actually changed. updates.md even keeps its own tiny changelog at the bottom, tracking edits to the process document itself, separate from changes to the Code of Conduct. The governance model applies to itself.
Turning a rewrite into a project plan
Two weeks after updates.md landed, issue #74, "Adopt Contributor Covenant 3," opened and immediately spawned fifteen sub-issues (#75 through #89). Each one was a discrete deliverable: rewrite the Enforcement Manual, rewrite the Reporting Guidelines, rewrite the FAQs, rewrite the CoC text itself, sync all of it to djangoproject.com, then announce it, separately, on the Django blog, the forum, Discord, DSF Slack, and Reddit. A rewrite this size doesn't happen as one PR. It happens as a checklist of small, assignable, individually reviewable pieces.
The actual pull requests show how messy that still is in practice. PR #90 opened February 10 and closed the same day, unmerged. A first attempt at the policy rewrite that didn't pan out. PR #91, opened minutes later, was the one that actually worked: +1,475/-790 lines, merged five weeks later on March 16. PR #97 closed the loop on April 15 with a comparatively small +217/-90, formally adopting Contributor Covenant 3. Start to finish, from PR #68 (which first brought these docs into git for change tracking, back on January 10) to PR #97 merging, the whole rewrite took about three months. Most of which was us allowing time for the community to read, comment, and ask questions. The actual work was a few days of writing and reviewing.
The paper trail that replaces "trust us"
The same PR that added updates.md also added a GitHub Action that regenerates CHANGELOG.md automatically on merge. It's not a list of diffs. It's a list of decisions, in plain language, with the reasoning attached. One real entry from the April 15 rewrite:
📝 remove weapons policy since we don't host in-person events directly. this makes more sense as guidance for affiliated events so I'll move it there in the process-docs PR
That's a documented reason for a scope decision, sitting in a public file anyone can read without asking. Multiply that by every entry in the changelog and that's the actual mechanism behind "trust us" becoming "here's the commit history." Not a promise, a habit, enforced by a bot that runs on every merge whether anyone remembers to update the changelog by hand or not.
Our GitHub Action expects a script to be at scripts/update_changelog.sh in the repo. View ours at https://github.com/django/code-of-conduct/blob/main/scripts/update_changelog.sh
What happens after a report comes in
The process above covers how the document changes. Reports of actual violations run through a separate mechanism, described in full in the working group manual and the reporting guide.
Every report lands in one inbox, conduct@djangoproject.com, which fans out to the whole working group. The goal is acknowledgment within a day and an initial response within a week, though the manual is upfront that volunteer coordination sometimes takes longer than that. A decision on next steps needs at least two working group members to agree. Anything severe enough to warrant legal advice needs a majority. Outcomes run up the enforcement ladder: private warning, 30 to 90 day suspension, 90-plus day suspension, permanent ban. Lower rungs get skipped when severity calls for it.
The record-keeping is worth copying too. Every case gets a randomly generated code name, things like "home shelf" or "stunned bulb." Every reported person gets their own persistent code name, like "Person A" or "Blue Jay," so the working group can track repeat patterns across cases without a real name ever touching the primary tracking sheet. A second spreadsheet, access-restricted separately from the first, holds the only mapping from code names back to real identities. Most of the working group can discuss a case, even in public, without either of them knowing who it's actually about.
The code name generator
Those code names come from a small Google Apps Script bound to the tracking spreadsheet, not a service or a library where we're sending sensitive data off to a third party. To install it, open the spreadsheet, go to Extensions > Apps Script, paste the script into Code.gs, and save. Reload the spreadsheet and a "Django CoC" menu shows up next to the built-in ones.
To use it, select the cell where you want a code name and click Django CoC > Generate Code Name. It picks one adjective and one noun at random from two 100-word lists, joins them with a hyphen, and drops the result into the active cell (something like amber-anchor). If the cell already has a value, it asks before overwriting.
Record keeping spreadsheets
The record-keeping actually lives across three separate spreadsheets, each with a different level of access.
The Report Tracker is the working record. One row per case, using code names instead of real identities, with columns for status, resolution source, safety risk, and consequences. The code name generator menu lives on this sheet.
The Person Identity Key is a second, more restricted spreadsheet. It's the only place that maps a code name back to a real name, and it tracks report counts and the highest consequence recorded against that person across cases. Access to it can be limited to a smaller subset of the working group than the Report Tracker itself, so members handling a case can look for patterns without necessarily knowing who they're looking at.
The Public Tracker doesn't touch either of those directly. It pulls a single "Annual Stats" tab out of the Report Tracker with IMPORTRANGE, aggregate counts only (reports, people named, warnings, suspensions, bans, and so on), nothing case-level. That's the sheet behind the statistics Django publishes publicly.
Borrow honestly
None of this was invented from scratch, and the working group says so directly. sources.md traces the lineage: the Ada Initiative's anti-harassment policy, through PyCon 2013, into Contributor Covenant. The 2026 rewrite additionally drew on published enforcement materials from the Python Software Foundation, OpenJS Foundation, and Mozilla, each one cited with the specific license it was borrowed under. Django's own materials are released under CC BY 3.0 for the same reason, so the next community doesn't have to start from a blank page either.
Proof it's still running
The process didn't stop being used the moment PR #97 merged. PR #106 added Djangonaut Space as an affiliated program in May. PR #108 added Django Commons in July. Both went through the same lightweight path described in affiliated-programs.md: adopt a complementary CoC, name a point of contact, publish transparency reports at least annually. This wasn't a one-time project. It's infrastructure now, and it's still picking up new communities.
If you want to fork this
Start with updates.md and the issue template it depends on. That's the whole meta-process in about a hundred lines. Copy the CODEOWNERS pattern if you have anything resembling a board or steering committee that should have a harder veto than your day-to-day maintainers. Read the working group manual end to end before you build a report-handling process from scratch, most of the hard judgment calls are already made in there.
And if you want the record-keeping spreadsheets as actual templates instead of a description, here they are, cleaned of real data and history. Each link opens a "Make a copy" prompt instead of our live copy, so you get your own independent version:
- Report Tracker, the case-by-case log with the code name generator built in
- Person Identity Key, the restricted sheet mapping code names back to real names
- Public Tracker, which pulls the Annual Stats tab out of the Report Tracker via
IMPORTRANGEfor anything you publish externally
Copying doesn't rewire them to each other. The IMPORTRANGE formula in your copy of the Public Tracker will still point at our Report Tracker, not yours, since Sheets copies the formula text as-is. After you copy both, open the Public Tracker, find the IMPORTRANGE formula on the Annual Stats tab, and replace our spreadsheet URL with the URL of your own copy of the Report Tracker. The first time it runs against the new URL, Sheets will show a #REF! error with an "Allow access" link. Click it once and the formula resolves.
A Code of Conduct is an exercise in trust. The processes and mechanics we've put in place are designed to make that trust verifiable, not just assumed. If you want to borrow them, please do. If you have improvements, please share them! We're available on email at conduct@djangoproject.com or open an issue against the working group repo and we'll respond.
24 Aug 2026 2:00pm GMT
Python Software Foundation: The PSF D&I Workgroup is Starting Office Hours in July!
Starting Tuesday 28 July, 2026, the PSF Diversity & Inclusion (D&I) Workgroup is opening its virtual doors once a month on Discord. Come chat with workgroup members from all over the world!
Doing diversity and inclusion work in tech can feel isolating sometimes. You might be organizing a meetup, writing a code of conduct, trying to get funding for your community, or helping people feel welcome, often in your spare time, and wondering if anyone else is wrestling with the same things.
They are. We are! And we would love to get all of us in the same room.
This July, the PSF D&I Workgroup will be hosting monthly office hours within Discord. These will be open, text-based conversations where we encourage you to ask questions, sha
re what you are working on, and connect with other people who care about making the Python community more welcoming.
The details
The PSF D&I Office Hours will be on the last Tuesday of every month. Because our community is spread across the globe, we will alternate between two times so we can cover as many time zones as possible:
-
1 PM UTC / 9 AM US Eastern
-
9 PM UTC / 5 PM US Eastern
Our first session will be on Tuesday, 28 July 2026 at 1 PM UTC. Here is roughly what that looks like around the world:
|
Region |
Local time on 28 July |
|
US Pacific, Los Angeles - (UTC-7h) |
6:00 AM |
|
US Eastern, New York - (UTC-4h) |
9:00 AM |
|
Brazil, São Paulo - (UTC-3h) |
10:00 AM |
|
UTC |
1:00 PM |
|
West Africa, Lagos - (UTC+1h) |
2:00 PM |
|
Central Europe, Amsterdam / Berlin / Madrid - (UTC+2h) |
3:00 PM |
|
East Africa, Nairobi - (UTC+3h) |
4:00 PM |
|
Iran, Tehran - (UTC+3:30h) |
4:30 PM |
|
India, New Delhi - (UTC+5:30h) |
6:30 PM |
|
China, Beijing - (UTC+8h) |
9:00 PM |
|
Japan, Tokyo - (UTC+9h) |
10:00 PM |
|
Australia, Sydney - (UTC+10h) |
11:00 PM |
If 6 AM in Los Angeles or 11 PM in Sydney made you wince, do not worry. The August session will be at 9 PM UTC, and we will keep alternating from there.
You will find us in the #psf-diversity channel on the PSF Discord. If you're new to Discord, check out some Discord Basics to help you get started.
What will we talk about
Honestly? Whatever is on your mind related to Python, your communities, and D&I.
Since our workgroup exists to advise the PSF on diversity and inclusion, some conversations we are especially hoping to have include:
-
Ideas for policies, initiatives, and grant proposals to diversify the PSF missions. Feedback from the community about these topics will help the PSF D&I Workgroup provide recommendations to the PSF Board of Directors.
-
Your feedback, plain and simple. We want to understand how the PSF can better serve and grow a diverse membership, and we cannot do that without hearing from the community itself.
-
How things are actually going. Part of our job is measuring and sharing the PSF's progress on its diversity initiatives, and we would rather do that in conversation with you than in a report nobody reads. We also want to understand and learn about the current state of Python communities around the world.
No camera, no mic, no pressure
Office hours are text chat only.
Show up in your pajamas, join from the bus, lurk quietly for the first twenty minutes. It is all fine.
And if you cannot make it at all, the conversation stays in the channel, so you can catch up later when it suits you. If something in the chat sparks a thought you would like to share with us directly, you are always welcome to email the workgroup at diversity-inclusion-wg@python.org.
Bring your own language
Because we are the D&I Workgroup, our members come from around the world! Alongside the main conversation, we will open threads in other languages where possible. Depending on the presence of our members, we would be happy to chat in Spanish, Portuguese, Chinese, Hindi, French or even Persian! Let us know during the office hour if you have a specific language you hope to converse in, or jump in with whichever language thread feels like home.
See you on the 28th!
The first office hour session is on Tuesday, 28 July 2026 at 1 PM UTC, in #psf-diversity on Discord.
Come say hi, even if it is just to tell us what you are working on with Python. We are really looking forward to meeting you!
24 Aug 2026 11:23am GMT
Armin Ronacher: Anger, Anxiety and Agency
Sean Goedecke wrote a post arguing that you should never be angry at work - a post with which I strongly agree. Anger can be a useful signal, but being angry at work rarely improves the situation. More often, it makes life worse for the people around you, many of whom have no more power over the source of your anger than you do. I did learn that lesson, but it did not come naturally. One thing in particular that I learned is that in a company there is a shared vision, and if you don't agree with it and are not in a position to change it, you should not start a mutiny, not even a small-scale one. Nothing good comes from that.
In the discussion around that topic, one of the most upvoted comments on the Lobsters thread asked a question I had to think about quite a bit:
How can you work in tech right now and not be angry?
In the context of the thread, this was clearly also about AI and agents. For me, the emotions I would expect in tech vis-a-vis these new developments are disorientation and anxiety, but not anger.
Anxiety as an emotion does not require someone to blame. Right now, I find it reasonable to feel anxious about an uncertain future. Who knows what our professions will turn into and what kind of world my kids will find themselves in when they enter the workplace? And if you've been in the industry for a long time, will the skills you've spent years acquiring still matter?
But anger is different from anxiety because anger needs to be directed somewhere. The feeling of anger suggests that somebody or something is doing something to you.
Who are you going to be angry at and why are you angry in the first place? One narrative that is pretty pervasive is that if AI will usher in productivity gains, those gains are going to benefit companies rather than employees. And well at least someone at Meta wants that. Yet I also find that plenty of people in leadership positions express doubt about AI. They see that an increasing share of their costs is being funneled directly to some large AI labs. They express worries about what will happen to their data and whether these large companies will step into their space instead of being partners.
My answer to the question of how you can not be angry in tech is that it's by no way the most only possible feeling. First of all, instead of being angry, you can simply be unsure. The feeling of uncertainty is a much more productive emotional state because it can lead to curiosity. Even if you don't find what's happening right now exciting, you can at least find it interesting. We have access to magic machines, and we can poke at them and see what happens. The second way is to feel genuine excitement. Once you move beyond curiosity, you can come away with a newfound feeling of power and freedom. A lot of the gains from AI aren't turning into productivity gains that are reflected in company profits but they're showing up instead in the number of side projects shipped by everybody not on their company's time.
The fact that this is happening shows us that owners and founders don't necessarily know what will happen. Ownership comes with agency, but it does not provide foresight, and this change is disorienting for everybody. I engage with plenty of people who project confidence in public and are much less certain in private. Many of them are placing bets, but they are talking with confidence about those bets, trying to stay afloat while the ground moves under them. They experience that uncertainty from a position where they can act on it, and they are often standing somewhere with a megaphone to get others on their side to increase their odds.
I feel that contradiction myself. I am simultaneously tremendously excited, but I am also unsure what will happen next. I do not know what it will mean to be a programmer in the future, and, as the owner of a company, I am also not sure where the high ground will be when this all settles. Much of what I learned over the years is changing rapidly, including ideas I considered fundamental to my craft and business. Some days that feels liberating, but on others I wake up feeling like the ground is crumbling beneath me.
Anxiety is an uncomfortable emotion because it acknowledges that you do not know what will happen and might not be able to stop it. On the other hand, anger can feel more actionable because, instead of saying "I don't know," you already have someone to blame. It turns a loss of control into a comforting story with a villain. But I feel that particularly when it comes to AI, it's easy to pick the wrong villain because of how disruptive the change is for everyone. Your engineering manager or leadership team might themselves feel uncertain about their future and just try to bolster their own confidence by projecting clarity and certainty.
That does not mean there are no villains. When this all plays out, some will profit and many will not. I'm afraid we're completely ignoring the impact this has on society at large, the climate, and the balance of the world as a whole. As excited as I am about the technology, I worry about Europe's lack of ambition and growing dependence on other countries. I have a lot of complex thoughts about what we're doing as an industry right now.
I don't know what the future of this industry will look like, and I don't know who will benefit from it and I don't think I'm alone with that. However I can only urge anyone who feels anger and looks for a villain right to instead remain curious instead. To be curious enough to understand what is changing, excited enough to experiment with it. And then, from what we learn, earn the right to decide when resistance is warranted and where to direct it.
24 Aug 2026 12:00am GMT
23 Aug 2026
Django community aggregator: Community blog posts
When Python is Too Slow

Python is a perfect language for Agile development, where requirements might change on the go. Especially if you are in a startup business, you will need to experiment and change things fast. However, Python is an interpreted language, and in certain situations you might need faster performance than what an interpreted language can provide. A common practice in these cases is using python-to-binary bindings, where the binary code is built with Rust, C++, or Go. In this article, I will explore bindings to Rust-based code.
How do the bindings work
The idea behind bindings is that you create a module with functions of a specific domain in a language that compiles to binary, and build it as a C-compatible dynamic library (.so on Linux, .dylib on macOS, .dll on Windows). Then a Python wrapper is built as a Python package and installed together with the dynamic library, allowing you to import and use functions that pass control to the corresponding functions in the dynamic library. On some occasions, classes can be used instead of functions. If any parameters are complex, they must be serialized in the wrapper and passed to the dynamic library as a JSON string or as a set of individual primitive parameters.
An experiment with benchmarks
To try this Python-Rust communication, I vibe coded an experiment that reads a large CSV file and builds a new one with duplicates stripped out based on specified column indexes. In my test case, it was a 3 MB CSV file with data about European NGOs for the donation platform I am building, where I wanted to remove the NGOs that don't have website URLs listed. As benchmarked, the file was processed 4.3x faster with the Rust binding than directly with Python.
Here is the repo to get a first glimpse into the code and structure.
What is there to know about Rust
A few things about Rust: Rust packages are built with Cargo, which is the equivalent of pip, virtualenv, and setuptools combined. A single package is called a crate, and it can be published to crates.io, the equivalent of PyPI. To create a Python-to-Rust binding, the standard approach is to use Rust's PyO3 library together with maturin, a build tool installable as a PyPI package.
Rust syntax is not the most developer-friendly compared to Python or Go, but with today's AI agents, most Python-native code can be ported to it fairly easily. The good thing about Rust and Go compared to C++ is that you don't have to manage memory at a low level or work with pointers directly.
The package structure
The common file structure can be:
thepackage_rs/ # the package - self-contained and installable
├── Cargo.toml # crate manifest (pyo3, etc.)
├── pyproject.toml # maturin build backend config
├── src/lib.rs # Rust implementation
└── python/
└── thepackage_rs/
└── __init__.py # Python wrapper
Once the code is ready, you build it with:
(.venv) maturin develop --release
This builds the Python package and installs it into the current virtual environment. You can also get the wheel at thepackage_rs/target/*.whl, built for your specific operating system.
Rust in Django
When developing Django websites, the biggest bottlenecks are usually not in the language itself, but in the connections to databases, file systems or object storage, and APIs. Still, in cases where you need to process large amounts of data or do heavier calculations, using a binary instead of Python makes sense. The orjson library, and DRF renderers built on top of it such as django-orjson or drf-orjson-renderer, are good examples of this - Rust boosts the speed of building or parsing JSON 2-10x compared to a Python-native implementation. The best places to use Rust replacements are background tasks, management commands, template parsing (see the experimental django-rusty-templates), and occasionally views or middleware.
Final words
So Python itself is good enough, especially when it comes to code readability and speed of development. However, when needed, certain parts can be improved 2 to 10x just by rewriting them as Python-Rust bindings. Just keep in mind that when it comes to views with data from the database or Elasticsearch, post-processing - such as reordering in Python or Rust - is an antipattern; do that directly in the queries instead. Finally, keep in mind, that building with Rust will need extra dependencies and maintainance in your workflows.
Cover photo by Alex Tepetidis
23 Aug 2026 5:00pm GMT
21 Aug 2026
Django community aggregator: Community blog posts
Fuzzy String Matching in Django and PostgreSQL
Gerald Carlton and I will be presenting on fuzzy name search at DjangoCon US 2026 on Monday, August 24, and this is the companion blog post. Searching for a person by name is harder than it looks: names might be typed differently by different operators or change over a person's lifetime; for example, Smith could be entered as Smyth, Smythe, or Smidt, and Weiss as Weiß. Although names are particularly susceptible to misspelling, these strategies apply to all fuzzy string matching.
21 Aug 2026 6:00pm GMT
06 Aug 2026
Planet Twisted
Hynek Schlawack: Production-ready Python Docker Containers with uv
Starting with 0.3.0, Astral's uv brought many great features, including support for cross-platform lock files uv.lock. Together with subsequent fixes, it has become Python's finest workflow tool for my (non-scientific) use cases. Here's how I build production-ready containers, as fast as possible.
06 Aug 2026 12:00am GMT
23 Jun 2026
Planet Twisted
Glyph Lefkowitz: Adversarial Communication
As I have discussed in previous posts, "AIs" can make mistakes. In fact, they do make mistakes, and their mistake-making patterns are such that where and how they will make mistakes is both uncertain and constantly changing.
Thus, in any scenario where you want to attempt to make "productive" use of "AI", you must have a system in place for checking every result. Not checking some results; checking every result. If each result might have a consequence for you (and if it didn't have a consequence, why bother automating it?) and you cannot predict in advance which kinds of results will need verification, then verification is always required.
The verification often ends up being just as expensive as doing the work in the first place, which means that if you want your usage of "AI" to be personally profitable, you have to find someone else to externalize the cost of verification onto. This person becomes your adversary, and, if you are successful, your "AI's" victim.
The Ladder-Climber And Their Reverse-Centaur Rungs
One way that this constellation of facts can straightforwardly assemble themselves into a dystopian nightmare is the phenomenon, described by Cory Doctorow, of the reverse centaur. This is when your employer non-consensually turns you into the verification system. The "AI" does the fun part of initially performing the work, and then you do the boring part where you check if the robot is right and clean up its messes, even if everyone already knows that it would, in aggregate, be cheaper for you to do the work in the first place.
Reverse centaurs can be made from any automation, not only "AI" automation. I think that there is a reason that this term happens to have emerged in the "age of AI", though, and not with earlier automation technologies (even those which were considerably more viscerally horrific). That reason is: the wrongness of "AI" output is not merely a technical feature that must be compensated for, it is a generalized externality.
As I mentioned above, if you are responsible for the entirety of the work, both extruding the "AI" output and checking it, it's usually cheaper to have humans do the entirety of the work to begin with. When humans do the writing directly, we can check as we go, and thus verification doesn't need to be as comprehensive.
When "AI" coding advocates say "code review is the bottleneck", what they are observing is that the LLM is still rolling the dice for each PR, and a human is still necessary to verify that each of those rolls is a winner. But calling this process "code review" is a bit of a misnomer; it's not really "code review" in the traditional sense, it's human understanding.
Before the advent of "AI", the human understanding was implicit in the process of writing the code in the first place1, and the code review was a way of diffusing and extending that understanding. Now that the code can be authored with no initial understanding taking place, that cost has not gone away, it has moved.
Human understanding was always the bottleneck.
However, this is taking a collaborative view of a software project, where satisfying the needs and solving the problems of your customers are the goals. We can see that "AI" is a bad tool to satisfy those goals, because all it's doing is converting the first half of the work, that of understanding the code as you write it, to understanding the agent's output as you read it.
What if, instead, we were to take the view that every software company is a Hobbesian nightmare, red in tooth and claw? In this view, the only goal of a software project is for the individual developers to make their promo cycles and get their bonuses. Given that there is only a certain amount of money to go around, this is a zero-sum game where each programmer wants to look more productive than their colleagues.
Pretty much every organization finds it easy to reward "productivity" as expressed by lines of code emitted, but the benefits of doing thorough and thoughtful design, analysis, and code review very difficult to reward. In this world, an LLM is an invaluable tool for the sociopathic ladder-climber, particularly if your legacy organization is still structuring their workflows as if the person prompting the bot is "writing" the code, and then they get to foist off the act of "reviewing" the code onto someone else.
Here, the prompter effectively externalizes the cost of the LLM's failures but internalizes any benefits. The prompter will vibe-code a big feature, so large that the assigned reviewer can't possibly comprehend it all effectively. When this happens, the reviewer will, eventually, be pressured to approve it, even if they can try to spot a few problems along the way. The reviewer has their own work to get back to, after all, the obligation to review the prompter's (read: the bot's) code is a drain on their time that they are not going to get rewarded for.
If this feature is a big success, the prompter gets a promotion. If it causes a big issue, well, the reviewer must not have been careful enough.
This is why LLMs are "good for coding", and also why their biggest promoters keep having outages.
The Generative Gish Galloper
Coding is the biggest "success story" of this type of adversarial communication, but it is by far not the only instance of such a thing. LLMs create a new form of leverage that can turn Brandolini's law from a linear advantage into an exponential one. If you are engaged in a political debate where you want to overwhelm the other side in nonsense, an LLM can generate bullshit faster than it is physically possible for a human being to type, let alone respond thoughtfully. There is an asymmetry to the utility of this weapon as well: only one side of the political spectrum wants to flood the zone and destroy trust in institutions and the concept of truth. There's a good reason that the fascists love it.
Straightforward Spam and Fraud
This is kind of obvious, but LLMs can generate lightly-customized, plausible-looking text much more quickly than any human being. This facilitates their use in fraud, spam, and scams. In a spamming or fraudulent interaction, once again, the costs are externalized onto the victim: the recipient of a spam message has to do all the work of "checking" the LLM's output. Spammers already expect very low hit rates from boilerplate, and if the LLM can increase those percentages from 1% to 5% the technology will pay for itself; they don't need anything like reliable accuracy.
Customer "Support"
If you have any kind of commercial relationship with a company, I probably don't even need to mention this: customer "support" bots are a misery. Everybody knows it at this point. But customer support is usually conceptualized by businesses as an adversarial interaction, because it is a cost center. They maintain internal metrics on time-to-resolution and try to optimize them. Implicitly, this creates a dynamic where the goal of the customer service agent's job is not to solve your problem, but to emit noise that will cause you to think your problem is resolved, or to give up, as fast as possible. Unsurprisingly, LLMs can emit this noise faster than humans can, getting those customers off the phone. But those customers will remember those interactions, and the story outside the TTR metrics is horrible.
Similarly to the situation in software development, LLMs can look very good on paper for customer support, but mostly what they are doing is illuminating the problems with the industry's existing metrics, by turning "winning the metrics battle against the customer" into a more obvious and immediate defeat for the company's long term reputation.
"Education"
In 2026 it is sadly a fact of life that students cheat all the time using "AI", and that this cheating is very successful, in that the teachers find it very hard to detect.
LLMs are great for cheating on schoolwork because the student is externalizing the work of the checking onto the teachers, who are often starting at a disadvantage to begin with, at least in the US.
My view is that this is happening because of a divergence in the way that students vs. teachers (or, more accurately, "the broader educational system") view grading.
When a student is asked to write an essay, the teachers see the effort as both intrinsically worthwhile for the student, as well as useful as a pedagogical tool to evaluate and react to the student's progress. The student, by contrast, sees a stumbling block designed to knock them off the path to success and into a permanent underclass. It is no wonder that the student sees "AI" as useful to their own goals and has no compunction about deploying it.
There is a bitter irony that the ability to understand the inherent value of actually writing the essay on their own is the sort of thing that students can really only learn by writing a bunch of essays. There's no way that I can think of which makes the benefit legible as long as a shortcut is available.
The net effect here is a downward spiral, where the already-wobbling educational system is sustaining an attack that it doesn't have the resources to recover from. The individual students' attacks against their teachers and their schools' grading systems might appear to momentarily succeed, but they will win the battle and lose the war.
Spamming "For Good"?
Usually when we talk about someone unilaterally choosing to enter into an adversarial relationship, that's an "attack" and for good reasons we have a negative impression of the attacker. However, I would be remiss if I did not point out that there are some cases where the relationship was already adversarial; just because you're the attacker doesn't mean that you are evil.
For example we might imagine use-cases like automatically filing appeals for prior authorizations against health insurance. It's relatively well-known at this point that the main way for-profit insurers maintain their margins is by denying claims right up to the line of the policies themselves being fraud, so using a spamming tool to fight them might be entirely justifiable2 in that case.
Similarly, using an LLM could be justified in a fight against a company refusing to honor a warranty. One could imagine using an LLM to immediately generate replies and escalations.
However, even in imagined cases like these, the underlying problem is that the insurers and the vendors already have a tremendous amount of structural power, so it is more likely that they will have the advantage in deploying a communications weapon like an LLM, as well as enacting policies to simply ignore any LLM-based communication that you might submit. Worse, if these strategies were to become widespread, they might provide an excuse to reject any communications by feeding them into an unreliable "LLM detector" and issuing an automated "computer says no" even to hand-written correspondence.
It is also worth stressing that these cases are imagined, as compared to the very real coworker-abuse, spam, scam, fraud, and disinformation campaigns being waged in real life today.
Therefore, while legitimate uses might exist, it's hard to imagine that there's anywhere they would be genuinely valuable and sustainable. In the best case "AI" will provide a temporary advantage for underdogs that will provoke an arms race which the resource-advantaged adversaries will win in the long run, in the worst case the arms race itself will cement permanent structural change that will make things worse.
"Search" By Stealing
Most of the adversarial utility of "AI" is on the "write" side, since write-amplification is more obviously aggressive than reading. But the "read" side of LLMs - summarization and question-answering - can be a form of attack as well.
To begin with, the act of reading itself is currently enormously destructive, but that's arguably not a fundamental aspect of this technology. They could set reasonable rate-limits and respect things like robots.txt, as search engines have for decades now. They could also refrain from committing criminal levels of copyright infringement. But, today, using "AI" tools does suborn this sort of out-of-control crawling.
More insidiously, consider the scenario described in this YouTube video. The LTT Bros decided to try Linux again, and in the course of so doing, they had problems. When trying to solve these problems, they were faced with a choice: they could consult Reddit, or they could ask an LLM. Asking an LLM would "gaslight the heck out of" them, but they still found it preferable, because they would at least get an answer without getting yelled at.
Initially this sounds great. But it also means that you want to extract knowledge from a community, while mechanically eliding any values or norms that the community may want to impart as part of offering that knowledge. As someone who spent many years in a community tech support role, this is worrying. Many requests for support are people asking how to do things that will momentarily solve a superficial problem but create a long-term reliability problem or even an immediate security risk, that the question-asker doesn't want to hear about. Consider the question "I'm tired of entering my password so much, how do I make it so my laptop unlocks automatically". An obsequious chatbot will helpfully tell you how to do this without pushback.
But, this is also a sort of ethically murky area. The Linux community is somewhat famously, for many years now, a toxic cesspool of general hostility, misogyny, etc. It is certainly a good thing that people can get access to this knowledge without subjecting themselves to abuse. But it also means that the people with the power and the privilege to change the community for the better can just quietly withdraw, rather than fixing the problems. It also means that the positive elements of culture cannot be transmitted, and people will have no opportunity to learn about unknown unknowns.
In this case, the "adversarial" communication is with society. The thing that using an LLM for search lets you do is withdraw from society and avoid forming any personal connections. There are some personal connections which are painful and annoying, and so that can feel like a momentary balm. But the need to make connections in general is, like, the concept of society itself.
Who Am I Hurting?
LLMs are good at adversarial communication. They are so good at it, relative to their other benefits, that they will tend to make communications adversarial if you are not remaining vigilant about the possibility that it might do so. My request to you, dear reader, if you are going to use such tools, is to always ask yourself, "who might I be hurting, if I use an LLM for this?"
If you're using an "AI", who is its adversary? If you haven't given it one yet, who might the "AI" turn into an adversary? Who might you overwhelm with an asymmetric amount of output, or, if you're receiving information and not sending it, who are you taking that information from without consulting?
Figure out the answers to these questions and conduct yourself accordingly; the answer might be "yourself".
Acknowledgments
Thank you to my patrons who are supporting my writing on this blog. If you like what you've read here and you'd like to read more of it, or you'd like to support my various open-source endeavors, you can support my work as a sponsor!
-
One of the reasons that software developers tend to prefer greenfield development is that when you are given a blank page, you can project your own specific understanding onto it. You can structure the codebase in a way that works for your brain, down to the variable naming conventions and the module layouts. LLM-assisted development makes everything into instant brownfield work, which makes developers instantly miserable; even those who are excited about the technology will frequently complain about how it feels like their agency has been stolen and their joy in the work has been diminished. But I digress. ↩
-
Modulo the massive amount of other externalities involved in using LLMs, of course, but I don't have the time or energy to get into those here. ↩
23 Jun 2026 8:06pm GMT
09 Jun 2026
Planet Twisted
Hynek Schlawack: How to Ditch Codecov for Python Projects
Codecov's unreliability breaking CI on my open source projects has been a constant source of frustration for me for years. I have found a way to enforce coverage over a whole GitHub Actions build matrix that doesn't rely on third-party services.
09 Jun 2026 12:00am GMT
