My three free WordPress plugins are no longer distributed through the WordPress.org plugin directory. They are still free, still GPL, still maintained, and they now live and update from alovio.org instead.
I want to be precise about what this was not, because the obvious assumption is the wrong one. It was not the code. There was no guideline violation in them, no security problem, and no complaint from anyone using them. Nobody reported a bug I ignored. The plugins that were closed are the same plugins you can download today, written and supported by the same person.
The reasons are not mine to argue in public. I said what I had to say to the people whose decision it was, they considered it, and the matter is closed. I am not going to relitigate it on my own website, where only one side is present.
What I will write about is the part that turned out to be far more interesting than the disagreement: what happens, mechanically, when the channel your software updates through stops being yours.
What you own and what you rent
A GPL plugin is yours. That is the whole point of the licence — nobody can take the code away, nobody can stop you handing it to someone else, and if a distribution channel closes you can always put the zip on your own site. I believed that, and it is true.
It is also almost beside the point.
What you own is the code. What you rent is the channel it travels down, and the channel is the thing that holds your users.
The mechanics nobody reads until they need them
When someone installs a plugin from a directory, their WordPress asks that directory for updates. Twice a day, for as long as the site exists, a server you do not control is asked a question about software you wrote, and answers on your behalf. You are not in that conversation. You cannot see it, join it, or change it.
Moving is supposed to be easy, and technically it is. You add an Update URI header to the plugin pointing at a host of your own, and from that moment WordPress stops asking the directory about your plugin and asks you instead. It has worked since WordPress 5.8. The server on the other end has to answer one question in JSON. It took me an afternoon.
And it does nothing whatsoever for any site that already has the plugin installed.
You cannot ship the update that adds your update channel
It took me too long to see this properly.
The version of the plugin that knows how to update itself from my server has to reach the installed sites somehow. The only road to them is the channel I am leaving. If that road is open, I don’t need the new one yet. If it is closed, I cannot use it to deliver the thing that would have replaced it.
There is no clever way around this. Not a smaller payload, not a staged rollout, not a different hook. The capability has to be on the site before the site stops listening, or it will never get there.
So a couple of hundred installations are frozen at whatever version they happen to be running, indefinitely, until a human being touches each one.
And nothing appears to be wrong
The second half of the trap is worse than the first, because nothing breaks.
A dead update channel does not produce an error. No warning, no notice, no line in a log that anyone reads. The site asks its question, receives nothing useful, and concludes — perfectly reasonably — that there is no update available. The Plugins screen reports that everything is current. It will go on reporting that while a finished security fix sits on my laptop.
Those users are not ignoring me. They have no idea there is anything to ignore. From inside their own admin, a plugin that will never be updated again looks exactly like a plugin that is up to date.
Which makes the fix a human one
This is the part I would want someone to have told me earlier.
The only way to reach a site that can no longer hear you through software is to reach the person who runs it. An email. A page they will find when they search the plugin’s name. Something that gets them to click Upload Plugin once, by hand — after which they are on a channel I control, and this never has to happen again.
Which means the ability to recover rests entirely on something you either did or did not do months earlier: do you have any relationship with your users outside the platform?
If everyone using your plugin found you through a directory, and that directory was the only place you ever spoke to them, then you do not have users. The directory has users, and it was lending them to you. I would like to put that more gently, but I cannot find a version that is also true.
A directory does not lend you distribution. It lends you the relationship — distribution is just what the relationship happens to be made of.
What I do now
Four things. Three of them are nearly free if you do them at the start, and nearly impossible to do afterwards.
Ship an Update URI from day one. Even when the server behind it has nothing to say but “nothing new here.” The point is not the feature; the point is that the capability is already installed in the field. A plugin that has always asked my server can be pointed somewhere else whenever I choose. A plugin that has never asked my server cannot be told to start.
Own a release pipeline before you need one. Mine is a small service on my own domain. I hand it a zip and a version number; it records a checksum so a truncated upload can never reach anyone, and it answers update checks with the current version and where to get it. What matters is not that it is clever — it isn’t — but that publishing a release is something I can do this afternoon, by myself, without asking permission or waiting for a queue.
Keep a list, however small. Every person who has ever emailed me about a plugin is someone I can still reach when software cannot. For a long time I filed those threads as support tickets. They turned out to be the only part of the arrangement that was ever really mine.
Make your own site the canonical home. Documentation, install steps, changelog, screenshots. If the real page for your plugin lives on someone else’s domain, then every link anyone has ever shared points at a door you cannot keep open. Mine point at alovio.org, and the directory listing was the mirror — not the other way round.
This is not an argument against directories
The discovery a good directory gives a new plugin is real, large, and very nearly impossible to reproduce alone. Someone with a problem types four words into a search box and finds a thing you made. No amount of writing buys that. I would not pretend I built any of this without it, and I don’t think anyone should refuse it on principle.
The point is not avoidance. The point is knowing which parts of your work are standing on borrowed ground, so that it is a decision rather than a discovery. Be a good tenant: follow the rules of the building, carefully and in good faith. Just don’t mistake a tenancy for a deed.
Respect the room, know whose room it is
I wrote once about being a guest in someone else’s house — about redesigning part of a platform I did not write and do not control, and refusing to patch its core files, because a product that breaks on the next update is not a product.
That was about the platform you build on. This is about the platform you ship through, and the metaphor survives the move with one thing added: a guest should know which of their belongings are theirs, and which came with the house.
The code is mine. The traffic, the listing, the install count, the update channel, and above all the line to the person at the other end of it — those came with the house, lent for exactly as long as the arrangement lasted.
Enjoy the room. Keep your own keys.