Glossary

How a Bluesky threadgate Decides Who Can Reply to a Post

Taras Shynkarenko
Taras Shynkarenko
•Updated: •6 min read
How a Bluesky threadgate decides who can reply to a postHow a Bluesky threadgate decides who can reply to a post

TL;DR, Quick Answer

6 min read

Bluesky reply controls live in an app.bsky.feed.threadgate record whose record key matches the thread's root post. Its allow array takes up to 5 rules: mentionRule, followerRule, followingRule and listRule. An empty array means nobody can reply, and a missing array means anybody can. The same record holds up to 300 hidden reply URIs. Quote posts are controlled by a separate app.bsky.feed.postgate record, whose disableRule turns off embedding and whose detachedEmbeddingUris holds up to 50 detached quotes.

What is a Bluesky threadgate?

A Bluesky threadgate is the app.bsky.feed.threadgate record that decides who can reply to a thread. The lexicon describes it as a "Record defining interaction gating rules for a thread (aka, reply controls)." Reply controls on Bluesky are not a setting on your account or a flag on the post. They are this record, stored in your own repository.

It is a record of its own, not a field on the post. That design has a consequence people miss: you can add, change or delete reply controls on a post that is already live, because the post record itself never changes.

The lexicon pins down where the record has to live: "The record key (rkey) of the threadgate record must match the record key of the thread's root post, and that record must be in the same repository." A threadgate belongs to a root post, in the author's own repo, under the same rkey.

What fields does the threadgate record have?

Four, and two of them are required.

FieldTypeRequiredLexicon description
postat-uriYes"Reference (AT-URI) to the post record."
createdAtdatetimeYesNone
allowarray, max 5No"List of rules defining who can reply to this post."
hiddenRepliesarray of at-uri, max 300No"List of hidden reply URIs."

A full record that lets mentioned accounts and one list reply looks like this:

{
  "$type": "app.bsky.feed.threadgate",
  "post": "at://did:plc:abc123/app.bsky.feed.post/3kxyzpost",
  "allow": [
    { "$type": "app.bsky.feed.threadgate#mentionRule" },
    {
      "$type": "app.bsky.feed.threadgate#listRule",
      "list": "at://did:plc:abc123/app.bsky.graph.list/3kxyzlist"
    }
  ],
  "createdAt": "2026-09-24T10:00:00.000Z"
}

You write it with com.atproto.repo.createRecord, setting collection to app.bsky.feed.threadgate and rkey to the rkey of the post, which is the last segment of the post's AT-URI. Bluesky's thread gates page shows the same step in its TypeScript sample: const { rkey } = new AtUri(postUri).

Which allow rules can a Bluesky threadgate use?

Four rule types, each an object inside allow. Bluesky's documentation lists them with one-line definitions:

RuleWho can reply
app.bsky.feed.threadgate#mentionRule"Allow replies from actors mentioned in your post."
app.bsky.feed.threadgate#followingRule"Allow replies from actors you follow."
app.bsky.feed.threadgate#followerRule"Allow replies from actors following you."
app.bsky.feed.threadgate#listRule"Allow replies from actors on a list."

Three of the four carry no properties at all. listRule is the exception: its list field is required and takes the AT-URI of an app.bsky.graph.list record.

The rules add up rather than narrow down. Bluesky's sample puts mentionRule, followingRule and listRule in one array with the comments "allow mentioned users," "allow followed users" and "allow list members," so each rule opens replies to one more group.

mentionRule depends on how the post encodes its mentions. In a post record, a mention is a app.bsky.richtext.facet#mention facet, and the facet lexicon notes that "The text is usually a handle, including a '@' prefix, but the facet reference is a DID." Typing an @handle as plain text without a facet does not make it a mention in the record. Getting the facet's byte offsets right is its own problem, covered in the note on Bluesky facets byteStart and byteEnd.

The allow array caps at 5 items while there are only four rule types. The schema does not forbid repeating listRule, so the fifth slot is room for a second list.

A padlock hanging on a closed wooden gate, standing in for a thread where nobody can reply.

What is the difference between an empty and a missing allow array?

Everything. The lexicon draws the line in one sentence: "If value is an empty array, no one can reply. If value is undefined, anyone can reply."

allow valueWho can reply
MissingAnyone
[]Nobody
One or more rulesAnyone matching any rule

Bluesky's documentation phrases this at the record level instead: "If a thread gate record is present but empty, then nobody can reply," and "If a thread gate record is not present, then anybody can reply." Read the two sources together and there is a case the docs page skips. A threadgate record can exist with no allow field, for example one that only lists hiddenReplies. Under the lexicon's wording, that thread is still open to anyone. If your code hides a reply by creating a threadgate, and then someone reads "record present means gated," they will get the logic backwards.

Can you gate a reply in the middle of a thread?

No. The threadgate's rkey has to match "the thread's root post," so there is one threadgate per thread, attached to its first post. Replies further down cannot carry their own reply controls.

AdaptlyPost
AdaptlyPost

Start Your 7-Day Free Trial

All-platform analytics

Social Inbox

AI-powered assistant

The hiddenReplies array lives on the same root record, and it caps at 300 URIs. Bluesky's announcement of the feature, in app version 1.90, says "Only the original creator of the thread can hide replies," and that "All hidden replies will be placed behind a Hidden replies screen." They stay reachable there, "but much less visible." The same post warns that hidden replies, along with which posts the author hid, "are still public data." Anything in a threadgate record is readable by anyone who reads your repository.

A hand underlining a quoted passage in a printed book, illustrating quoting another person's post.

What is the postgate record?

The postgate is the threadgate's counterpart for quote posts. app.bsky.feed.postgate is a "Record defining interaction rules for a post," and it follows the same placement rule: its rkey "must match the record key of the post, and that record must be in the same repository."

FieldTypeRequiredLexicon description
postat-uriYes"Reference (AT-URI) to the post record."
createdAtdatetimeYesNone
embeddingRulesarray, max 5No"List of rules defining who can embed this post."
detachedEmbeddingUrisarray of at-uri, max 50No"List of AT-URIs embedding this post that the author has detached from."

embeddingRules has a single rule type today, app.bsky.feed.postgate#disableRule, described as "Disables embedding of this post." That is the switch behind turning off quote posts.

Note that the postgate's defaults differ from the threadgate's. For embeddingRules, "If value is an empty array or is undefined, no particular rules apply and anyone can embed." An empty array locks replies in a threadgate but leaves quotes open in a postgate. To block quotes you need an explicit disableRule.

The postgate also differs in scope. It matches "the record key of the post," not the thread's root, so any post, including a reply, can carry its own postgate.

detachedEmbeddingUris records the quotes you have already cut loose. Bluesky's 1.90 announcement describes it: "you can detach your original post from someone's quote post," and "Like blocks, quote post removals are public data." The array holds 50 URIs.

How does a client know a post is gated?

Through the post view, not by fetching the records. app.bsky.feed.defs#postView carries a threadgate field that returns the record along with the lists it references. The viewer state for the logged-in account adds two booleans, replyDisabled and embeddingDisabled, which a client can use to grey out the reply and quote buttons for that person.

A scheduling tool has one extra step. The threadgate is a second record, so a scheduled post with reply controls means two writes: the post, then the gate under the same rkey. The note on how to schedule Bluesky posts covers the posting side, and both writes count against the limits described in the note on the Bluesky API rate limit.

Publishing a post with reply controls
1
Write the post. Create the post record and keep its AT-URI.
2
Take the rkey. It is the last segment of the post's AT-URI.
3
Write the threadgate. Same repository, collection app.bsky.feed.threadgate, same rkey.
4
Add a postgate if quotes should be off. A separate record with the post's rkey and a disableRule.
Each gate is its own write on top of the post.

Frequently asked questions

How do I stop everyone from replying to a Bluesky post through the API?

Create an app.bsky.feed.threadgate record with the post's rkey and "allow": []. The lexicon says "If value is an empty array, no one can reply."

Can a Bluesky threadgate allow only my followers to reply?

Yes. Add app.bsky.feed.threadgate#followerRule to allow. Bluesky defines it as "Allow replies from actors following you."

How many rules can one threadgate hold?

Five. The allow array has a maxLength of 5 in the lexicon.

Can I change reply controls after a post is published?

Yes. The threadgate is a separate record, so you can create, update or delete it without touching the post itself.

How do I turn off quote posts on Bluesky through the API?

Create an app.bsky.feed.postgate record with the post's rkey and add app.bsky.feed.postgate#disableRule to embeddingRules. An empty array does not block quotes.

Are hidden replies private?

No. Bluesky says hidden replies, and which posts the author hid, "are still public data." They sit in the threadgate's hiddenReplies array, which anyone can read.

AdaptlyPost
AdaptlyPost

Start Your 7-Day Free Trial

All-platform analytics

Social Inbox

AI-powered assistant

Who can hide replies on a Bluesky thread?

Only the original creator of the thread can hide replies, according to Bluesky's 1.90 announcement. The hidden URIs go in the hiddenReplies array of the threadgate, up to 300 of them. Hidden replies sit behind a Hidden replies screen and stay reachable there.

Does an empty embeddingRules array turn off quote posts?

It does not. In a postgate, an empty or undefined embeddingRules means no particular rules apply and anyone can embed the post. To block quotes, add app.bsky.feed.postgate#disableRule.

How do I detach a quote post from my original post on Bluesky?

Add the AT-URI of the quote to the detachedEmbeddingUris array of the postgate for your post. The array holds up to 50 URIs. Bluesky notes that, like blocks, quote post removals are public data.

Can one threadgate combine several allow rules?

Rules add up. Each rule in allow opens replies to one more group, so mentioned users, followed users and a list can sit in the same array. The array holds up to 5 rules, and listRule needs the AT-URI of an app.bsky.graph.list record.

Was This Article Helpful?

Let us know what you think!

See us more often in Google

One click marks AdaptlyPost as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.

Before you go...

AdaptlyPost

AdaptlyPost

Schedule your content across all platforms

Manage all your social media accounts in one place with AdaptlyPost.

All-platform analytics

Social Inbox

AI-powered assistant

Related Glossary Terms

Related Articles