Search 12,366 communities

Market Breakdown 01: Makers & Indie SaaS

Reddit as a marketing channel. Prepared from ThreadFox operating data, October 3-31, 2026.

One-page summary

Measure Value
Communities in this segment (appendix A) 279
Communities where ThreadFox found at least one thread 278
Threads found in 28 days / per week 31,095 / 7,773
Asks (threads that passed first-stage screening) in 28 days / per week 24,117 / 6,029
Trend, threads per active community, week 1 to week 4 32.4 to 57.0
Share of all threads found (all segments, incl. unassigned) 8.3%
Candidate replies skipped as off-topic or not a fit (share of candidates drafted) 7,618 (29.5%)
Replies posted / communities posted in 5,769 / 138
Share of all replies posted 23.5%
Communities with a link-or-offer prohibition (of those with candidates) 49 of 260 (18.8%)
Removal rate among checked replies 1.8% (38 of 2,124 checked)
Communities that banned the account 13 (6.5% of communities posted in, counting only bans that followed posts)
Share of recorded site visits from replies 19.5% of visits, from 24.4% of tagged replies
Data support Strong (largest segment by threads and replies)

Read this first.

  • This is the deepest pool in the data: 31,095 threads and 24,117 asks in 28 days, and the segment where ThreadFox posted most (5,769 replies in 138 communities).
  • Replies mostly stayed up: 38 of 2,124 checked replies were removed. Bans happened in 13 communities, and the median ban came after 1 prior post, so some rooms enforce promotion rules from the first reply.
  • Roughly one community in five that produced candidates forbids links or offers (49 of 260), and one room (a code-projects room) alone refused the account on hundreds of candidates. The work is choosing rooms, not writing more replies.
  • Visits per tagged reply are somewhat below the site average, but the segment supplies about a fifth of all recorded visits from replies because of its volume.

All figures are for Oct 3-31, 2026, taken from ThreadFox's own queue, send log, comment checks, ban log and the sales site's visit counters. Appendix B holds the SQL for every number. No income or results guarantees are made or implied anywhere in this report.

1. Market definition

Makers and indie software founders who post something they built, a side project, a micro-SaaS, an open-source tool or a beta, and ask the room for feedback, first users or first customers. The core rooms are the side-project, build-in-public, show-your-product and micro-SaaS communities. Founder, startup, co-founder and entrepreneur rooms (including the India, UAE and Singapore startup rooms) are included because their posts ask for the same things. Buyers here are other makers; the product on offer is usually tooling, services or feedback that helps a launch.

The segment is defined by a list of 279 community names (Appendix A), assigned from the community name and checked against the search phrases that surfaced threads in each room. 278 of them produced at least one thread in the window and 138 received at least one reply. Communities are matched case-insensitively. Rooms that fit no segment were left unassigned and are not in any figure here.

2. Market size and trend

Definitions. A thread found is a post in a member community that ThreadFox's searches returned. An ask is a thread that passed ThreadFox's first-stage screening (a recent self-post, not in an excluded room, not already contacted, with something of the poster's own and a request for help or feedback). A second stage then judged many of these not a fit when drafting; the off-topic share is shown in the summary and in section 4, so treat asks as an upper bound on addressable demand. Weeks are first-discovery weeks.

Week Threads found Asks Active communities Threads per active community Share of all threads found Threads created on Reddit that week ThreadFox replies posted
Week 1 (Oct 4-10) 4,465 2,609 138 32.4 23.1% 4,325 1,400
Week 2 (Oct 11-17) 4,522 4,054 108 41.9 13.6% 4,963 1,515
Week 3 (Oct 18-24) 10,201 8,546 199 51.3 10.3% 11,231 517
Week 4 (Oct 25-31) 11,907 8,908 209 57.0 5.3% 10,074 2,337

Over 28 days ThreadFox found 31,095 threads here, about 7,773 a week, of which 24,117 (about 6,029 a week, 77.6%) were asks. Threads found rose from 4,465 in week 1 to 11,907 in week 4. Read the trend carefully: over the same four weeks ThreadFox's discovery across all rooms grew from 19,304 to 224,766 threads a week as search coverage was widened, so the segment's share of all discovery went from 23.1% to 5.3%. The coverage-neutral figure is threads per active community, which moved from 32.4 to 57.0. Week 4 was 2.7 times week 1 in this segment, against 11.6 times across all rooms. Within the segment, discovery grew less than across the business as a whole, which means other segments gained coverage faster.

Replies posted by week also reflect operating decisions (posting volume varied widely by week across the whole business, for operating reasons: 4,480, 6,223, 3,379, 10,505 replies by week), so posting volume should not be read as demand. Of 25,831 candidate replies queued for this segment, 5,769 were posted, 9,915 were skipped and 9,687 expired unposted.

3. Demand signals

What ThreadFox's searches matched most. These are ThreadFox's own search phrases; one thread can match several. The last two columns show how many threads a phrase matched in week 1 and week 4. A phrase with zero in week 1 was added to the searches later, so its growth reflects search changes, not buyer behaviour.

Search phrase Threads Share of segment threads Asks Week 1 Week 4
"i built" 1,441 4.6% 1,208 233 201
"i made" 374 1.2% 282 117 48
"side project" 351 1.1% 311 55 89
"get customers" 281 0.9% 238 74 66
"would love feedback" 272 0.9% 240 27 69
"feedback on my" 256 0.8% 200 96 16
"honest feedback" 250 0.8% 238 0 55
"i built an app" 184 0.6% 143 39 26
"launched my" 174 0.6% 155 47 31
"i created" 155 0.5% 148 0 44
"looking for feedback" 154 0.5% 132 28 47
"built this" 150 0.5% 145 0 34

Wording themes in candidate-reply titles (24,642 titles; a title can fall in several themes; counted by keyword, no titles are reproduced):

Theme Titles Share
Asks for feedback or critique 1,844 7.5%
Asks for testers, beta or early access 829 3.4%
About users, customers, clients, traffic, sales or downloads 1,936 7.9%
About marketing, promotion, ads or growth 1,480 6.0%
Announces something built, launched or made 7,332 29.8%
Hiring or looking for a provider 1,364 5.5%
About price or cost 492 2.0%
Phrased as a question or request for advice 5,409 22.0%

What people are asking for, in summary. Most posts announce a finished or half-finished product (a web tool, a browser extension, an AI-wrapped utility, an open-source project) and ask for honest feedback, a handful of testers or early users. A second group asks how to get a first customer or why signups are flat. A smaller group looks for co-founders, developers or help finishing a launch, or asks how to build in public. Phrases about having no signups or needing first customers are the clearest buying-intent signal; the larger "i built" and "i made" phrases mainly find showcase posts.

4. Channel access

ThreadFox checks each room's rules and each thread before drafting. Of 25,831 candidate replies, 9,654 were skipped with a recorded reason across 208 communities. The table groups those reasons.

Skip reason (grouped) Replies Share of skipped-with-reason Communities affected
off-topic or not a fit 7,618 78.9% 177
forbids link or offer 672 7.0% 49
account refused by room 649 6.7% 8
no buying evidence 311 3.2% 67
help-only room 206 2.1% 21
internal or technical 143 1.5% 45
room or thread gone 34 0.4% 19
flair required 21 0.2% 3

At the community level, of the 260 communities with candidate replies: 49 (18.8%) forbid links or offers (the rules or the thread forbade them), and, in other communities, post flair the account could not supply was the blocker in 3, help-only rules (a reply may not name a product) in 21, and refusal of the account or submission in 11. ThreadFox posted in 138 communities. Separately, 1,040 threads were dropped before drafting because the community was on ThreadFox's exclusion list. Access is mixed. A minority of rooms forbid links or offers, a few ask for help-only replies, and a handful of large rooms account for most blocked candidates (listed above), so room selection removes most of the friction.

Rooms with the most blocked candidates: coolgithubprojects (account refused by room, 360); sideproject (forbids link or offer, 155); bangalorestartups (forbids link or offer, 114); startupsolofounder (forbids link or offer, 110).

5. Risk

Removal. Of 5,769 replies posted, 2,124 (36.8%) were re-checked on Reddit at least once (typically one and two days after posting). In the latest check, 2,073 were visible, 38 removed (1.8%), 8 collapsed and 5 deleted or not found. A further 50 replies in this segment, 0.9% of those posted, appear in ThreadFox's hidden-replies log. Removal is low. This is also the largest checked sample of the eight segments, so it is the best-supported removal figure in this series.

Bans. The ban log shows 13 ban events in 13 communities in this segment (9 of them after ThreadFox had already posted there, 249 posts in total before the first ban). Median posts before a ban: 1. By week: week 1 2, week 2 1, week 3 4, week 4 6. The log records how the ban was detected (9 account-banned notices, 2 no-comment-box notices, 2 other forms), not the moderators' stated reason, so a reason cannot be quantified from this file. Bans reached startup, SaaS and open-source rooms. Because the median ban came after only about one prior post, the trigger is often the first visible promotion in a strict room, not accumulated volume.

Banned communities in this segment (up to ten): australianstartups, blockchainstartups, entrepreneurship, femalefounders, foss, goodopensource, microsaas, opensourcealternative, rss, saas.

6. Timing

Times are UTC; US Eastern was UTC minus 4 hours throughout the window.

UTC window (US Eastern) New threads created Share of segment threads Replies posted Checked Still visible
00-05 (8 PM-1 AM) 4,879 15.9% 1,414 583 97.3%
06-11 (2-7 AM) 7,549 24.5% 1,387 559 97.3%
12-17 (8 AM-1 PM) 10,880 35.4% 1,679 627 97.9%
18-23 (2-7 PM) 7,461 24.2% 1,289 355 98.0%
Weekday (UTC) New threads created Share Replies posted Checked Still visible
Sun 3,285 10.7% 650 346 99.1%
Mon 4,250 13.8% 900 752 96.8%
Tue 4,152 13.5% 516 279 100.0%
Wed 3,912 12.7% 971 259 97.3%
Thu 4,734 15.4% 697 165 97.6%
Fri 5,303 17.2% 971 137 98.5%
Sat 5,133 16.7% 1,064 186 94.1%

The busiest hours for new threads were 15:00 UTC (1,907 threads), 16:00 UTC (1,890 threads), 13:00 UTC (1,886 threads). New threads peak in the US morning to early afternoon. Because makers post throughout the day and survival does not vary by window, speed after a post appears probably matters more than the clock; the data does not record reply latency, so this is not tested. Weekday figures are indicative only: coverage grew through the month and the window holds five Saturdays and four of every other day. Check coverage is uneven across windows and weekdays, and cells with fewer than 50 checks are flagged. Still-visible rates differ little by window because almost every checked reply survived; differences between windows are within what small samples produce.

7. Reach

Replies that carried a tracked link are tied to visits on the sales site. In this segment 5,461 tagged replies produced 34,454 recorded page hits, 19.5% of all 176,527 hits from tagged replies, from 24.4% of the 22,381 tagged replies. That is 6.3 hits per tagged reply (all segments: 7.9), and 39.1% of tagged replies drew at least one hit. Hits are page loads, not unique people, and include automated fetches such as link previews, so use them to compare segments, not to count readers. Across the whole site, Reddit-sourced hits were 44.8% of 489,065 recorded hits (direct 26.9%, the site's own rules pages 19.5%).

Rooms that drew the most hits in this segment: sideproject (5,953 hits from 931 replies); imadethis (4,613 hits from 875 replies); buildinpublic (2,183 hits from 609 replies); micro_saas (2,177 hits from 293 replies); saasbuild (1,510 hits from 131 replies); founder (1,230 hits from 189 replies).

This segment supplies the most recorded visits in absolute terms because it is where most replies went. Per tagged reply it is somewhat below the site average, so its advantage is breadth, not depth.

8. Competitive notes: what gets through

Reply type Checked Visible Removed Removed share
No offer, no link 776 757 15 1.9%
Offer, no link 72 72 0 0.0%
Offer and link 1,276 1,244 23 1.8%
Reply kind Checked Visible Removed Removed share
reply 1,530 1,502 19 1.2%
followup 592 569 19 3.2%
correction 1 1 0 0.0%
catchup 1 1 0 0.0%

Communities with at least 15 checked replies (22 here), lowest survival first: producthunters (19 of 20 visible), foss (52 of 54 visible), saasdevelopers (52 of 54 visible), micro_saas (151 of 156 visible), entrepreneurs (68 of 70 visible).

Screening also shapes what is reachable. Of 31,095 threads found, 6,831 (22.0%) were dropped before drafting. Top drop reasons: author already contacted (2,135), not a self-post (1,458), excluded community (1,040), too old (674), no own product (567).

The crowd in these rooms is other makers promoting their own work. Replies that named the product and carried a link stayed up at about the same rate as replies that did not, which indicates that in rooms where posting is allowed, the room's rules, not the link, decide the outcome. The data cannot test reply quality or wording.

9. Recommended approach

  • Make this the anchor segment. Rank rooms by asks per week and by survival, and concentrate effort in the handful of rooms that combine both; the top five rooms already account for more than half of replies.
  • Screen every room's rules for link and offer prohibitions before drafting; 49 of 260 rooms with candidates would have rejected a linked reply.
  • Treat bans as a room-by-room signal. Where the first reply is removed or the account is banned, stop in that room rather than adjusting wording.
  • Lead with a specific, useful comment on the poster's project and mention the product only where it answers the poster's actual question.
  • Prefer threads that state a need (no signups, first customers, looking for testers) over pure showcases.

What this data cannot tell you. It cannot say how many repliers became customers, only that visits reached the site. Phrases reflect ThreadFox's searches. Removal is measured early, so later moderation is not captured.

Appendix A: Segment community list

279 communities (lower-case names, ordered by threads found). Rule: assigned by community name against a keyword list for this segment, in a fixed order so each community lands in exactly one segment; rooms that match no list are unassigned. Search phrases were used to check the lists (for example, rooms returning mostly shopping or hiring phrases), but no community was assigned on phrases alone, because phrase-only assignment pulled in job boards and consumer rooms.

sideproject, imadethis, sideprojects, buildinpublic, micro_saas, coolgithubprojects, entrepreneurs, founder, saas, cofounderhunt, indianstartups, startupindia, saasdevelopers, webapps, indiebiz, saasbuild, startupsolofounder, technepal, youngentrepreneur, investors, bangalorestartups, developersindia, foss, cofoundermatch, getstartups, startup_ideas, nocode, hyderabadstartups, websitefeedback, saasforsale, hackathon, solopreneur, moroccopreneur, prettyusefulwebsites, producthunters, angelinvesting, indianentrepreneur, uae_startups, indie_startups, startupshelpstartups, entrepreneurridealong, threejs, devtools, saasinvestors, showyourproduct, devlk, startups, entrepreneur, microsaas, saassolopreneurs, cli, startupaccelerator, launchmystartup, indiastartups, computervision, theraceto10million, pakistanidevs, crmsoftware, ideavalidation, crm, esp32projects, ukstartups, indiandevelopers, macrostartups, startupaccelerators, acquirestartup, singaporestartups, banglorestartups, startupninjas, buildtoship, hackernews, indiehackersindia, startupinvesting, b2bsaas, startupbeginnings, weirdsideprojects, pythonprojects2, showmeyoursaas, mercorai_workers, hwstartups, startupindiajobs, aceo, gostartupindia, thefounders, codereview, projects, microlaunch, microsaasbr, saassales, startupideasindia, rss, roastmyidea, startupideas, opensourcealternative, entrepreneurship, dubai_real_estate, vancouverstartup, bookmarkmanagers, entrepreneurshipuae, indiehackers, startupsargentina, indiancofounders, newproducts, startupegypthub, streetwearstartup, sweatystartup, startupcolombia, directorymakers, trueenterpreneur, bootstrappedsaas, howtoentrepreneur, startupsavant, dkstartup, muslimpreneurs, opensource, opensourcez, startupmind, italiastartups, madeinpython, thesideproject, trueopensource, fxtraderss, saasacquire, advancedentrepreneur, startupsanduxdesign, startupsindubai, chilestartup, saasselection, 3dprintentrepreneurs, algerianstartups, freightbrokerstartup, startup, startupdach, techstartups, foundermail, opensourcedialer, pinprojects, producthuntlaunches, women_entrepreneurs, desifounder, femalefounders, goodopensource, indiedevelopers, indiedevesp, roastmystartup, apparelstartup, entrepreneurph, entrepreneursfr_, leanstartup, pakstartups, silverpalaceofficial, startup_funding, acquiresaas, australianstartups, blockchainstartups, chennai_gaming, fintechstartups, indianfoundershub, london_entrepreneurs, startupcirclecanada, bangalorenewprojects, berlinstartups, deutschestartups, kenyastartups, nashvillestartups, saasdecoded, saasfeedbackclub, startupfuture, startups_eu, startupsmapconnect, truckingstartups, boxtruckstartup, buildstartuptogether, entrepreneurdb, foodentrepreneurindia, foundershub, foundersplot, foundertestlab, humansarespaceorcs, indiesaas, junkremovalstartup, manchesterstartups, saas_rankings, saascritic, shareyoursideproject, startup_de, startupmalaysia, startupshowcase, acquireindiansaas, actuallyopensource, afghanentrepreneur, agencyfoundershub, andhrastartups, arduinoprojects, atmentrepreneurs, b2bsaasdesign, bai_lu, bootstrapfounders, caretakerfanprojects, chai_unofficial, coimbatore_startups, diatomaceousearth, discoversaas, dropyoursaashere, edmontonstartups, edtechstartups, enterpreneurdna, entrepreneurtoolkit, eslopensource, feetscammerss, founder_to_ceo, founderoperations, foundersz, getsaasfeedback, glaceon, handshakeai_jobs, homeservicestartup, indiaentrepreneur, indiefoundersindia, indiehackersworld, innospaceone, innovatorfoundervisa, kotastartupcommunity, latefounders, lean_startup, linuxprojects, lstartupmotivation, mauritianentrepreneur, mbzuai_prep_hub, montrealstartups, mumbai_flat_flatmates, mumbai_thane_meetups, nbengalurustartups, neopaceofficial, nepalfounders, nocodeplatform, nontechsaasfounders, opensourcedtools, opensourceesl, opensourceevolved, opensourcegames, opensourceware, prototypestartup, pureopensource, ratemystartupidea, realsideprojects, remotedevelopersindia, reno_entrepreneurs, saas_letsgo, saaschool, saasexpohub, saasorganic, saaspayments, saassignal, saastimes, saasvendormarket, saasverdict, sekai_multiverse, senegalentrepreneurs, showprojects, solofounders, solotechfounders, spaceopera, startup_communityy, startup_eu, startup_resources, startupbangalore, startupfinanceitalia, startupguides, startupsbyvets, startupsmaplaunch, swissfounder, trymystartup, underthestarss, weirdstartups, woodprojects, workspaceone, zerotofounder, startupincubatorsv

Appendix B: SQL

Run on read-only copies of the queue, reply-tag and commerce snapshots. :s = segment number (1 for this report). segment_map(community, segment) holds Appendix A (lower-case community name to segment). bans is the ban file loaded as (community, at, reason). items is limited to public reply kinds (reply, followup, catchup, correction). LATEST below stands for the latest non-unknown comment check per reply:

Show the query
-- LATEST
(select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l

Week buckets use first_at (found) or at (sends): week 1 up to Oct 10, week 2 up to Oct 17, week 3 up to Oct 24, week 4 after.

Show the 40 queries
-- size
select count(*) threads, count(distinct lower(f.community)) communities,
 sum(f.decision='kept') kept, sum(f.decision='dropped') dropped, sum(coalesce(f.decision,'')='') undecided
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s;
-- found_week
select case when substr(first_at,1,10)<='2026-10-10' then 1 when substr(first_at,1,10)<='2026-10-17' then 2 when substr(first_at,1,10)<='2026-10-24' then 3 else 4 end wk, count(*) threads, sum(f.decision='kept') kept, count(distinct lower(f.community)) communities
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s group by 1 order by 1;
-- all_week
select case when substr(first_at,1,10)<='2026-10-10' then 1 when substr(first_at,1,10)<='2026-10-17' then 2 when substr(first_at,1,10)<='2026-10-24' then 3 else 4 end wk, count(*) threads, sum(f.decision='kept') kept from found f group by 1 order by 1;
-- sent_week
select case when substr(at,1,10)<='2026-10-10' then 1 when substr(at,1,10)<='2026-10-17' then 2 when substr(at,1,10)<='2026-10-24' then 3 else 4 end wk, count(*) posted, count(distinct lower(x.community)) communities
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s where x.outcome='posted' group by 1 order by 1;
-- all_sent_week
select case when substr(at,1,10)<='2026-10-10' then 1 when substr(at,1,10)<='2026-10-17' then 2 when substr(at,1,10)<='2026-10-24' then 3 else 4 end wk, count(*) posted from sends x where x.outcome='posted' group by 1 order by 1;
-- posted
select count(*) posted, count(distinct lower(x.community)) communities,
 sum(x.kind='reply') replies, sum(x.kind='followup') followups, sum(x.kind='catchup') catchups, sum(x.kind='correction') corrections,
 sum(x.offer=1) with_offer, sum(x.link=1) with_link
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s where x.outcome='posted';
-- items
select count(*) candidates, count(distinct lower(i.community)) communities,
 sum(i.state='posted') posted, sum(i.state='skipped') skipped, sum(i.state='expired') expired,
 sum(i.state not in ('posted','skipped','expired')) other
from items i join segment_map m on m.community=lower(i.community) and m.segment=:s;
-- phrases
select j.value phrase, count(*) threads, sum(f.decision='kept') kept, sum(case when substr(first_at,1,10)<='2026-10-10' then 1 when substr(first_at,1,10)<='2026-10-17' then 2 when substr(first_at,1,10)<='2026-10-24' then 3 else 4 end=1) week1, sum(case when substr(first_at,1,10)<='2026-10-10' then 1 when substr(first_at,1,10)<='2026-10-17' then 2 when substr(first_at,1,10)<='2026-10-24' then 3 else 4 end=4) week4
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s, json_each(f.queries) j group by 1 order by 2 desc limit 15;
-- themes
select count(*) titles,
 sum(lower(i.title) like '%feedback%' or lower(i.title) like '%review my%' or lower(i.title) like '%roast%' or lower(i.title) like '%critique%' or lower(i.title) like '%thoughts on%') feedback,
 sum(lower(i.title) like '%test%' or lower(i.title) like '%beta%' or lower(i.title) like '%early access%') testing,
 sum(lower(i.title) like '%user%' or lower(i.title) like '%customer%' or lower(i.title) like '%client%' or lower(i.title) like '%subscriber%' or lower(i.title) like '%download%' or lower(i.title) like '%traffic%' or lower(i.title) like '%sales%') audience,
 sum(lower(i.title) like '%market%' or lower(i.title) like '%promot%' or lower(i.title) like '%advertis%' or lower(i.title) like '%growth%' or lower(i.title) like '%ads%') marketing,
 sum(lower(i.title) like '%launch%' or lower(i.title) like '%i built%' or lower(i.title) like '%i made%' or lower(i.title) like '%i created%' or lower(i.title) like '%just released%' or lower(i.title) like '%my first%') showing_off,
 sum(lower(i.title) like '%hire%' or lower(i.title) like '%hiring%' or lower(i.title) like '%looking for a%' or lower(i.title) like '%need a%' or lower(i.title) like '%for hire%') hiring,
 sum(lower(i.title) like '%price%' or lower(i.title) like '%pricing%' or lower(i.title) like '%how much%' or lower(i.title) like '%cost%' or lower(i.title) like '%charge%') pricing,
 sum(lower(i.title) like '%how do%' or lower(i.title) like '%how to%' or lower(i.title) like '%how can%' or lower(i.title) like '%advice%' or lower(i.title) like '%help%' or lower(i.title) like '%?%') question
from items i join segment_map m on m.community=lower(i.community) and m.segment=:s where i.title is not null and i.title<>'';
-- access_items
select case
 when i.draft_reason like 'prewrite: rules-no-offer%' or i.draft_reason like 'prewrite: links-only%' or i.draft_reason like 'links only:%' or i.draft_reason like 'prewrite: rules-no-link%' then 'forbids link or offer'
 when i.draft_reason like '%flair-required%' then 'flair required'
 when i.draft_reason like 'help-only room%' then 'help-only room'
 when i.draft_reason like 'prewrite: account-room-refused%' then 'account refused by room'
 when i.draft_reason like 'prewrite: invalid-room%' or i.draft_reason like 'prewrite: thread-removed%' then 'room or thread gone'
 when i.draft_reason like 'No verbatim paid-offer%' then 'no buying evidence'
 when i.draft_reason like 'prewrite:%' or i.draft_reason like 'undoing%' or i.draft_reason like 'profile post%' then 'internal or technical'
 else 'off-topic or not a fit' end cat, count(*) n, count(distinct lower(i.community)) communities
from items i join segment_map m on m.community=lower(i.community) and m.segment=:s where i.state='skipped' and i.draft_reason is not null and i.draft_reason<>'' group by 1 order by 2 desc;
-- access_base
select count(*) skipped_with_reason, count(distinct lower(i.community)) communities_with_reason
from items i join segment_map m on m.community=lower(i.community) and m.segment=:s where i.state='skipped' and i.draft_reason is not null and i.draft_reason<>'';
-- access_comm
select count(distinct lower(i.community)) communities_with_candidates,
 count(distinct case when i.draft_reason like 'prewrite: rules-no-offer%' or i.draft_reason like 'prewrite: links-only%' or i.draft_reason like 'links only:%' or i.draft_reason like 'prewrite: rules-no-link%' then lower(i.community) end) forbid_link_offer,
 count(distinct case when i.draft_reason like '%flair-required%' then lower(i.community) end) flair,
 count(distinct case when i.draft_reason like 'help-only room%' then lower(i.community) end) help_only,
 count(distinct case when i.draft_reason like 'prewrite: account-room-refused%' then lower(i.community) end) refused,
 count(distinct case when i.state='posted' then lower(i.community) end) posted_in
from items i join segment_map m on m.community=lower(i.community) and m.segment=:s;
-- excluded
select count(*) from found f join segment_map m on m.community=lower(f.community) and m.segment=:s where f.reason='excluded community';
-- found_drop_reasons
select f.reason, count(*) n from found f join segment_map m on m.community=lower(f.community) and m.segment=:s where f.decision='dropped' group by 1 order by 2 desc limit 6;
-- removal
select count(*) checked, sum(l.state='visible') visible, sum(l.state='removed') removed, sum(l.state='collapsed') collapsed, sum(l.state in ('deleted','not_found')) gone
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted';
-- hidden
select count(*) hidden, count(distinct lower(h.community)) communities from hidden_replies h join segment_map m on m.community=lower(h.community) and m.segment=:s;
-- bans
select count(*) ban_events, count(distinct b.community) banned_communities,
 sum(b.reason like 'account banned from this community%') account_banned,
 sum(b.reason like 'Reddit shows no comment box%') no_comment_box,
 sum(b.reason not like 'account banned from this community%' and b.reason not like 'Reddit shows no comment box%') other_form
from bans b join segment_map m on m.community=b.community and m.segment=:s;
-- ban_prior
select count(*) banned_comms, sum(p>0) with_prior_posts, sum(p) prior_posts from (
 select b.community, (select count(*) from sends x where lower(x.community)=b.community and x.outcome='posted' and x.at<min(b.at)) p
 from bans b join segment_map m on m.community=b.community and m.segment=:s group by b.community);
-- ban_examples
select b.community, count(*) n from bans b join segment_map m on m.community=b.community and m.segment=:s group by 1 order by 2 desc, 1 limit 10;
-- ban_week
select case when substr(b.at,1,10)<='2026-10-10' then 1 when substr(b.at,1,10)<='2026-10-17' then 2 when substr(b.at,1,10)<='2026-10-24' then 3 else 4 end wk, count(*) from bans b join segment_map m on m.community=b.community and m.segment=:s group by 1 order by 1;
-- post_block
select case when cast(strftime('%H',x.at) as int)<6 then '00-05' when cast(strftime('%H',x.at) as int)<12 then '06-11' when cast(strftime('%H',x.at) as int)<18 then '12-17' else '18-23' end blk, count(*) posted,
 sum(l.state is not null) checked, sum(l.state='visible') visible
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s left join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted' group by 1 order by 1;
-- post_dow
select strftime('%w',x.at) dow, count(*) posted, sum(l.state is not null) checked, sum(l.state='visible') visible
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s left join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted' group by 1 order by 1;
-- ask_block
select case when cast(strftime('%H',datetime(f.created_utc,'unixepoch')) as int)<6 then '00-05' when cast(strftime('%H',datetime(f.created_utc,'unixepoch')) as int)<12 then '06-11' when cast(strftime('%H',datetime(f.created_utc,'unixepoch')) as int)<18 then '12-17' else '18-23' end blk, count(*) threads
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s where f.created_utc>=cast(strftime('%s','2026-10-03') as real) group by 1 order by 1;
-- ask_hour
select cast(strftime('%H',datetime(f.created_utc,'unixepoch')) as int) h, count(*) threads
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s where f.created_utc>=cast(strftime('%s','2026-10-03') as real) group by 1 order by 1;
-- ask_dow
select strftime('%w',datetime(f.created_utc,'unixepoch')) dow, count(*) threads
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s where f.created_utc>=cast(strftime('%s','2026-10-03') as real) group by 1 order by 1;
-- reach
select count(distinct t.tag) tagged_replies, sum(p.n) hits, count(distinct case when p.n>0 then t.tag end) tags_with_hits, count(distinct lower(t.community)) communities
from reply_tags t join segment_map m on m.community=lower(t.community) and m.segment=:s
left join pageview_campaigns p on p.content=t.tag and p.source like 'utm:reddit%';
-- reach_total
select count(distinct t.tag) tagged, sum(p.n) hits from reply_tags t left join pageview_campaigns p on p.content=t.tag and p.source like 'utm:reddit%';
-- site_sources
select case when source like '%reddit%' then 'reddit' when source='direct' then 'direct' when source like 'utm:rules%' then 'site rules pages' else 'other' end src, sum(n) from pageviews group by 1 order by 2 desc;
-- reach_top
select lower(t.community) c, count(distinct t.tag) replies, sum(p.n) hits
from reply_tags t join segment_map m on m.community=lower(t.community) and m.segment=:s
left join pageview_campaigns p on p.content=t.tag and p.source like 'utm:reddit%' group by 1 order by 3 desc limit 8;
-- by_offer
select x.offer, x.link, count(*) checked, sum(l.state='visible') visible, sum(l.state='removed') removed
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted' group by 1,2 order by 1,2;
-- by_kind
select x.kind, count(*) checked, sum(l.state='visible') visible, sum(l.state='removed') removed
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted' group by 1 order by 2 desc;
-- top_comms
select lower(x.community) c, count(*) posted from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s where x.outcome='posted' group by 1 order by 2 desc limit 8;
-- members
select count(*) communities, sum(exists(select 1 from found f where lower(f.community)=m.community)) with_threads, sum(exists(select 1 from sends x where lower(x.community)=m.community and x.outcome='posted')) with_posts from segment_map m where m.segment=:s;
-- created_week
select case when f.created_utc<cast(strftime('%s','2026-10-11') as real) then 1 when f.created_utc<cast(strftime('%s','2026-10-18') as real) then 2 when f.created_utc<cast(strftime('%s','2026-10-25') as real) then 3 else 4 end wk, count(*) threads
from found f join segment_map m on m.community=lower(f.community) and m.segment=:s
where f.created_utc>=cast(strftime('%s','2026-10-04') as real) group by 1 order by 1;
-- all_created_week
select case when f.created_utc<cast(strftime('%s','2026-10-11') as real) then 1 when f.created_utc<cast(strftime('%s','2026-10-18') as real) then 2 when f.created_utc<cast(strftime('%s','2026-10-25') as real) then 3 else 4 end wk, count(*) threads
from found f where f.created_utc>=cast(strftime('%s','2026-10-04') as real) group by 1 order by 1;
-- ban_prior_detail
select b.community, (select count(*) from sends x where lower(x.community)=b.community and x.outcome='posted' and x.at<min(b.at)) p
from bans b join segment_map m on m.community=b.community and m.segment=:s group by b.community;
-- comm_survival_low
select lower(x.community) c, count(*) checked, sum(l.state='visible') visible, sum(l.state='removed') removed
from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted' group by 1 having count(*)>=15 order by 1.0*sum(l.state='visible')/count(*) asc, count(*) desc limit 5;
-- comm_checked_n
select count(*) from (select lower(x.community) c from sends x join segment_map m on m.community=lower(x.community) and m.segment=:s join (select c.permalink, c.state from comment_checks c where c.state<>'unknown' and c.check_no=(select max(c2.check_no) from comment_checks c2 where c2.permalink=c.permalink and c2.state<>'unknown')) l on l.permalink=x.permalink where x.outcome='posted' group by 1 having count(*)>=15);
-- globals
select (select count(*) from found),(select count(*) from sends where outcome='posted'),(select count(distinct lower(community)) from sends where outcome='posted'),(select count(distinct lower(community)) from found),(select count(*) from bans),(select count(distinct community) from bans),(select count(distinct permalink) from comment_checks where state<>'unknown');
-- blocked_top
select lower(i.community) c, case
 when i.draft_reason like 'prewrite: rules-no-offer%' or i.draft_reason like 'prewrite: links-only%' or i.draft_reason like 'links only:%' or i.draft_reason like 'prewrite: rules-no-link%' then 'forbids link or offer'
 when i.draft_reason like '%flair-required%' then 'flair required'
 when i.draft_reason like 'help-only room%' then 'help-only room'
 when i.draft_reason like 'prewrite: account-room-refused%' then 'account refused by room'
 when i.draft_reason like 'prewrite: invalid-room%' or i.draft_reason like 'prewrite: thread-removed%' then 'room or thread gone'
 when i.draft_reason like 'No verbatim paid-offer%' then 'no buying evidence'
 when i.draft_reason like 'prewrite:%' or i.draft_reason like 'undoing%' or i.draft_reason like 'profile post%' then 'internal or technical'
 else 'off-topic or not a fit' end cat, count(*) n from items i join segment_map m on m.community=lower(i.community) and m.segment=:s
where i.state='skipped' and (i.draft_reason like 'prewrite: rules-no-%' or i.draft_reason like 'prewrite: links-only%' or i.draft_reason like 'links only:%' or i.draft_reason like 'prewrite: account-room-refused%' or i.draft_reason like 'help-only room%') group by 1,2 order by 3 desc limit 4;

Appendix C: Method notes and limits

  • Snapshot taken Oct 31, 2026 21:10 UTC. The snapshot holds 24,587 sends with outcome posted (the business headline of 24,586 differs by one). Communities are counted case-insensitively, which gives 5,127 posted-in communities against 5,164 when case variants are counted separately.
  • Discovery counts reflect ThreadFox's search coverage, which expanded sharply during the month. They measure what ThreadFox could see, not the size of Reddit.
  • Removal is measured on the replies that were re-checked, not on all replies, and only in the first days after posting. Later removals are not captured.
  • Visit counts are all recorded page hits tied to a reply tag, not unique visitors, and include automated fetches. They are used for relative comparison only.
  • Bans are those in the ban log, detected when a post attempt or check failed. Bans that were never detected are not counted.
  • Search phrases are ThreadFox's own queries; they show what the searches matched, not an independent survey of demand.
  • Reddit post titles were used only to count keyword themes and to write the summaries in this report; none are reproduced, and no usernames, links or customer details appear.

This is one of the eight market reports in program 3.

One payment. Delivered by email link. All sales are final; no refunds.