Reddit marketing cadence per subreddit

Most cadence guides hand you a vibe (“1 to 3 posts per week”) and call it a strategy. A working autoposter has to compile cadence into actual numbers, in actual code, that decide right now whether you are allowed to post in r/X. Here are the numbers, taken straight out ofpick_thread_target.pyin the S4L pipeline.

M
Matthew Diakonov
9 min read

Direct answer (verified 2026-05-20)

At a minimum, set a 3-day floor between original threads in any subreddit you do not own, a 1-day floor in your own community subreddit, and a per-sub override knob so a stricter sub can carry a longer floor. Layer a project-level penalty on top: divide each project’s weight by1 + posts_in_last_7_daysso every recent original halves your odds against a never-posted peer.

Source: pick_thread_target.py in m13v/social-autoposter, lines 32-33 and 169-193.

The three knobs, in plain terms

Cadence per subreddit is not one number. It is three knobs that all have to agree before the picker lets you post.

0d

Own community floor

Minimum days between original threads in a subreddit you own and moderate. Default: 1.

0d

External sub floor

Minimum days in any subreddit you do not control. Default: 3. Override per-project withexternal_floor_days.

0d

Project halving window

Rolling window the picker counts your own original threads across. Each post inside it halves the project’s effective weight versus a peer at zero.

The decision the picker runs every time

Before a Reddit thread gets drafted, the picker walks four gates per (project, subreddit) candidate. Any gate that fails removes the candidate from the pool for this run. The remaining candidates go into a weighted draw.

per-subreddit eligibility check

1

Project enabled?

threads.enabled = true

🔒

Sub not banned

subreddit_bans.thread_blocked

Days since last >= floor

own=1d, external=3d

4

Weighted draw

weight / (1 + posts_7d)

The first three gates are deterministic. They turn an unlimited subreddit list into a small eligible set. The fourth gate is stochastic and runs only among the survivors, which is what stops the picker from getting stuck on the same sub night after night.

Why two defaults, not one

The split between an own-community floor of 1 day and an external-sub floor of 3 days is not aesthetic. The two are policed by completely different reviewers.

Your own community subreddit has one moderator team: you. Mod tolerance for daily posting from your own brand is high because there is no audience expectation that this is anything other than the brand’s home. Reddit-wide spam heuristics still apply, but the subreddit-level removal risk is approximately zero. A one-day floor mostly exists so you do not double-post inside the same UTC window by accident.

External subs are reviewed by a mod team you do not know, and by AutoMod, and by a community whose downvote button is the first line of enforcement. Posting at a 1-day cadence in r/SaaS or r/SideProject (whether you control the cadence or it is just the result of an enthusiastic schedule) reads like brand-spam to all three reviewers. 3 days is the smallest gap that consistently reads as “a person who cares about this community.” Smaller floors require a real contributor history in that sub to survive the same reviewers.

3d

External floor below 3 days is where mod-removal rate starts to climb in our pipeline data. We picked 3 because it is the smallest gap that consistently survives a fresh account in a strict sub.

S4L pipeline, scripts/pick_thread_target.py:33

The actual code, not a paraphrase

Here is the candidate builder. Read past the Python syntax and watch how each gate maps to a knob you control inconfig.json.

# scripts/pick_thread_target.py
DEFAULT_OWN_FLOOR_DAYS = 1
DEFAULT_EXTERNAL_FLOOR_DAYS = 3

def build_candidates(config):
    recent = recent_posts_by_sub(max_days=max(
        DEFAULT_OWN_FLOOR_DAYS, DEFAULT_EXTERNAL_FLOOR_DAYS, 14))
    thread_blocked = load_thread_blocked_subs(config)
    candidates = []
    for p in config.get("projects", []):
        t = p.get("threads") or {}
        if not t.get("enabled"):
            continue
        ext_floor = int(t.get("external_floor_days",
                              DEFAULT_EXTERNAL_FLOOR_DAYS))
        own = t.get("own_community")
        if own:
            own_floor = int(own.get("floor_days", DEFAULT_OWN_FLOOR_DAYS))
            slug = norm_sub(own.get("subreddit"))
            if slug not in thread_blocked:
                last = recent.get(slug)
                if last is None or last >= own_floor:
                    candidates.append((p, own, True, own_floor, last))
        for sub in t.get("external_subreddits") or []:
            slug = norm_sub(sub)
            if slug in thread_blocked:
                continue
            last = recent.get(slug)
            if last is not None and last < ext_floor:
                continue
            candidates.append((p, sub, False, ext_floor, last))
    return candidates

And the halving formula that runs over the survivors. This is the line that decides which of two eligible projects gets to ship tonight.

# Project-level halving: every original you posted
# in the last 7 days halves your odds against a peer
# that has not posted at all.
weights = [
    by_project[n]["project"].get("weight", 1)
    / (1 + recent_project_counts.get(n, 0))
    for n in names
]
chosen_name = random.choices(names, weights=weights, k=1)[0]

A project with base weight 15 that already shipped twice this week competes as 15 / 3 = 5. A peer project at base weight 10 that has not shipped at all competes as 10 / 1 = 10, so it wins the draw on most rolls. That is the entire mechanism that keeps any one product from monopolising your nightly Reddit slot.

Tuning per subreddit, not per platform

The defaults are a floor, not a recipe. Every entry in your subreddit list deserves its own override based on how the sub actually reacts to you. Four signals tell you which way to push the per-sub floor.

how to set the per-sub override

1

Open mod-removal rate

If more than 1 in 10 of your last 10 threads in this sub got removed by mods (not by score), push the floor to 5 or 7 days. The sub is signalling that your content is borderline; widen the gap.

2

Comment engagement floor

If a typical thread of yours in this sub clears 8 comments before the next one goes up, you have community room for a shorter floor. If your average is under 3, you do not. Cadence and engagement compound; a thread with no replies makes the next one look worse.

3

Subreddit size and velocity

Large fast-moving subs (500k+ members, top posts under 6 hours old) can absorb a 1-day cadence without flagging. Slow niche subs (under 30k, top posts older than 24 hours) need 5 to 7 days minimum, otherwise your face is on the front page for too long.

4

Account age in this sub

Accounts with fewer than 5 prior comments in a sub should keep the external default of 3 days for the first month, then revisit. The cadence is not about what you can technically do; it is about what reads as a real community member from the outside.

What this looks like in config.json

Concretely, here is one project block (slightly trimmed). The own-community floor lives inside the own_community object. The external floor is one number that applies to every entry in external_subreddits unless an entry carries its own override.

"threads": {
  "enabled": true,
  "posting_account": "<your username>",
  "external_floor_days": 3,
  "own_community": {
    "subreddit": "r/your_brand_sub",
    "cadence": "daily",
    "floor_days": 1
  },
  "external_subreddits": [
    "r/SaaS",
    "r/SideProject",
    "r/indiehackers",
    "r/Entrepreneur"
  ]
}

If a sub deserves a stricter floor (say r/Entrepreneur is removing your threads), promote it from a bare string to an object carrying its own floor_days. The picker reads either shape.

The most common cadence mistake

Treating cadence as a per-account schedule (“3 posts a week, evenly spaced”) is what gets accounts shadowbanned. That schedule says nothing about which subreddit each post lands in, and 3 posts a week into the same 4 subs is 36 posts per sub per quarter. The subreddit-level reviewer sees that number; the platform-level reviewer does not.

The fix is to invert: pick the subreddit first, check its floor, then post. The account-level cadence emerges as a side effect of which subs are eligible tonight, not as a target you aim at.

what to actually enforce

  • Per-subreddit floor between original threads (3d default external, 1d own).
  • Per-sub override knob for stricter or looser subs.
  • Rolling 7-day project halving so one product can't hog slots.
  • Subreddit ban list checked before the floor check, not after.
  • Comments and original threads tracked on separate cadence rules.
  • Account pinned per (project, subreddit) for thread creation.

Where the cadence stops being a number

Below a certain density (say one original thread per sub per week, plus three or four comments) the floor stops being the binding constraint. What matters is whether each thread reads as a real contribution. A 5-day floor with low-effort content gets you removed faster than a 2-day floor with one specific observation that only this sub would find useful.

Floors exist to keep you from being obviously a marketing schedule. They do not exist to make low-effort content survive. That part is on the draft.

Want this picker running against your subreddit list?

If you want the per-sub floor, override knob, and project halving running against your own list of subreddits and accounts, we can wire it up on a call.

Frequently asked questions

What is a safe floor between original threads in the same subreddit?

Three days for any subreddit you do not own. That is the DEFAULT_EXTERNAL_FLOOR_DAYS value in the picker, and it is the number we will not let the scheduler cross even if a project has only one external sub configured. In your own community subreddit, where moderators are your team, one day is fine.

Should the cadence be the same for every subreddit?

No. The floor is a default, not a ceiling on configuration. Every subreddit entry can carry a per-sub floor_days override. Larger subs with stricter mods get longer floors (5 to 7 days). Niche subs with active engagement and a flair specifically for your kind of content can tolerate shorter floors. The default is the worst-case safe assumption.

How do I keep one big subreddit from eating all my posting slots?

Layer a project-level penalty on top of the per-sub floor. We multiply each project's base weight by 1 divided by (1 plus number of original threads it posted in the last 7 days). One recent post halves your odds against a never-posted peer with the same base weight. Two recent posts third them. The floor stops you from spamming one sub; this stops you from spamming one product.

Does this floor apply to comments too, or just original posts?

Just original posts in this calculation. Comments use a separate gate: a per-account comment_blocked list of subreddits where the account has already been removed or shadowbanned for commenting. Mixing the two in one cadence rule causes false positives, because being banned from r/X for commenting does not mean you cannot post a thread on a different account in r/X.

What about per-account cadence on the same subreddit?

Pin one account per subreddit per project for thread creation. The pipeline tags every block with the account that hit it (the comment_blocked and thread_blocked entries carry an account field). Rotating accounts inside the same sub looks like ban evasion to admins. The cadence rules are per (sub, account), not per (sub, project), even though we only track the latter in the picker.

How do I tell the picker that a sub has banned me without deleting it from my list?

Add the sub to subreddit_bans.thread_blocked (for original threads) or subreddit_bans.comment_blocked (for comments) in config.json. The picker calls load_thread_blocked_subs(config) and removes them from the candidate pool. Entries carry added_at, reason, account, and noticed_by_project so a future audit can reverse the ban if the sub's policy changes.

Why a 7-day window for the project halving, not 30?

Reddit's anti-spam heuristics work on rolling short windows. 30 days is too long to recover from one mistake. 7 days lines up with how the platform treats a fresh week of activity and matches the recent_window_days default in the rest of the engine. It is short enough that a paused project naturally rebalances back into rotation.

s4l.aibooked calls from social
© 2026 s4l.ai. All rights reserved.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.