Author: onetwothreeadmin

  • AI prompt libraries grow stale faster than you think

    AI prompt libraries grow stale faster than you think

    AI prompt libraries grow stale faster than you think
    Photo: Ginny from USA via Wikimedia Commons (CC BY-SA 2.0)

    If you’re running an online business solo or with a small team, you’ve probably built a collection of AI prompts by now. A folder of “good ones” you return to when you need to draft a landing page, summarize research, or outline a content calendar.

    Most operators treat these prompts like recipes: write once, use forever. But AI prompts aren’t static assets. They degrade faster than you expect, and the reasons aren’t obvious until your output quality drops.

    Model updates change response behavior silently

    When Claude, GPT-4, or Gemini ships an update, the model’s interpretation of your prompt can shift. A prompt that returned concise bullet points in May might produce verbose paragraphs in July. The wording stays identical; the output doesn’t.

    Most platforms don’t version their models transparently at the API level. You’re often using “claude-3-5-sonnet” or “gpt-4o” as a rolling label, not a frozen snapshot. When the provider patches the model—fixing bugs, adjusting tone, reweighting training data—your saved prompts inherit those changes without warning.

    This isn’t hypothetical. In June 2026, a widely-used AI assistant updated its default verbosity setting, and operators across social media reported that their “write a 150-word summary” prompts suddenly returned 300-word responses. The prompt text hadn’t changed. The model had.

    Context windows and token limits shift

    Prompt libraries often include complex multi-step instructions: “First, extract key themes. Second, rank by relevance. Third, output as JSON.” These work well when you’re operating within a model’s context window, but as you add more examples, reference documents, or conversation history, you approach token limits.

    When a prompt that worked perfectly at 2,000 tokens hits a model’s 8,000-token context ceiling, the AI starts truncating your input or skipping steps. You won’t get an error—just incomplete output.

    Operators who save prompts without noting the surrounding context (how much history was in the thread, how large the input document was) often can’t reproduce results later. The prompt is the same, but the conditions aren’t.

    Your business needs evolve faster than your prompts

    A prompt you wrote in February to draft newsletter intros might have assumed a specific audience size, tone, or content format. Six months later, your subscriber count has doubled, your niche has narrowed, and your voice has shifted.

    The prompt still runs. It just produces output for a business that no longer exists.

    This is the subtlest form of staleness. The AI isn’t broken, and the model hasn’t changed. You have. But because the prompt still works, you keep using it—and wonder why the output feels off.

    How to keep your prompt library functional

    Date every prompt when you save it. Add a line at the top: Created: 2026-07-09 | Model: claude-3-5-sonnet | Context: 3K tokens. When you return to it three months later, you’ll know whether it’s worth running as-is or needs a refresh.

    Test your top five prompts monthly. Pick the ones you use most—content outlines, email drafts, research summaries—and run them with fresh input. If the output has drifted, you’ll catch it early.

    Version your prompts like code. When you tweak a prompt, save the new version separately. Don’t overwrite the original. If the update makes things worse, you can roll back. A simple naming convention works: landing-page-draft-v1, landing-page-draft-v2.

    Document what the prompt assumes. If it expects a specific input format (a bulleted list, a 500-word block, a CSV), note that. If it works best with a certain model or context size, write it down. Future you will thank present you.

    When to retire a prompt

    If you haven’t used a prompt in 60 days, archive it. Don’t delete it—just move it to a separate folder. Stale prompts clutter your library and tempt you to reuse output patterns that no longer fit your business.

    If a prompt requires more than two rounds of editing to produce usable output, rewrite it. The goal of a prompt library is speed. If you’re spending ten minutes massaging AI output every time, the prompt isn’t saving you time—it’s costing you focus.

    Want to see how other operators manage their AI workflows? Reply with your biggest prompt-library frustration—we’ll feature the best answers in an upcoming issue.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • SEO traffic declines after switching hosts—DNS TTL is why

    SEO traffic declines after switching hosts—DNS TTL is why

    SEO traffic declines after switching hosts—DNS TTL is why
    Photo by Justin Morgan on Unsplash

    Move a WordPress site to a new host, watch organic traffic drop 15–30% for three to five days, then recover. If you’ve migrated hosting recently, you’ve probably seen this pattern. The culprit isn’t downtime, broken redirects, or angry Google crawlers—it’s DNS Time To Live (TTL) settings interacting badly with search engine cache behavior.

    Most solo operators treat host migration as a one-afternoon task: export database, move files, update DNS A record, wait. But DNS propagation isn’t instant, and search engines don’t immediately trust the new IP. The gap between those two realities creates a window where crawlers hit stale IPs, time out, or mark pages unreachable.

    What TTL does during migration

    DNS TTL tells browsers and crawlers how long to cache your domain’s IP address before checking again. If your TTL is set to 86400 seconds (24 hours)—a common default—and you migrate hosting, visitors and bots will keep hitting the old IP for up to a full day after you update DNS.

    That’s fine for human visitors using browsers with retry logic. It’s terrible for search crawlers operating on tight schedules. Googlebot doesn’t wait around. If your old host shuts down the account before TTL expires, crawlers see timeouts. Timeouts signal unreliability. Unreliability triggers temporary ranking suppression while Google reassesses your site’s health.

    The fix is simple but requires planning a week ahead: lower your DNS TTL to 300 seconds (five minutes) at least 48 hours before migration. This ensures that by the time you flip the DNS A record, cached lookups expire within minutes, not hours.

    Why old hosts break this silently

    Most shared and managed WordPress hosts auto-cancel accounts within hours of migration completion. You export your files, move DNS, and assume the old server stays online long enough for TTL to expire. It doesn’t.

    If your old host deactivates your account six hours after DNS changes, but your TTL is still set to 24 hours, a large percentage of cached DNS lookups will resolve to a dead IP for the next 18 hours. Crawlers see repeated failures. Analytics show a sudden drop in organic sessions. By the time TTL expires and traffic recovers, you’ve already lost several days of visibility in search results.

    Hosts rarely warn you about this because DNS management sits outside their direct responsibility—it’s handled by your registrar or a separate DNS provider like Cloudflare. The coordination gap means the problem only surfaces after migration is complete.

    The pre-migration checklist

    Start by logging into your DNS provider (Cloudflare, your registrar, or wherever your nameservers point). Locate the A record for your root domain and www subdomain. Check the TTL value—if it’s above 3600 seconds (one hour), lower it to 300.

    Wait 48 hours. This gives the current high TTL time to expire across the internet’s DNS cache layers. If you skip this step and lower TTL five minutes before migration, the old 24-hour TTL is still active everywhere—your change won’t take effect in time.

    Migrate your site. Update DNS A records to the new host’s IP. Keep the old hosting account active for at least 24 hours after DNS changes, even with the low TTL. This provides a safety buffer for any lagging DNS resolvers or aggressive caching layers.

    Monitor Google Search Console’s crawl stats and Coverage report during the 72 hours post-migration. If you see a spike in server errors or timeouts, your TTL window was too short or the old host deactivated too early. You can’t fix it retroactively, but you’ll know what broke.

    When managed hosts handle DNS

    Some managed WordPress hosts—Flywheel, WP Engine, Kinsta—offer DNS management as part of their platform. If your domain’s nameservers point directly to your host, TTL control sits inside their dashboard, and migration becomes trickier.

    These hosts typically manage TTL automatically, and you may not have manual override. The workaround: move DNS to a standalone provider (Cloudflare’s free tier works) at least a week before migration. Point your domain’s nameservers to Cloudflare, replicate all DNS records, lower TTL, then migrate hosting. It adds a step, but it gives you control over the timing.

    If you’re migrating to a managed host that includes DNS, ask support whether they lower TTL automatically during migrations. Most don’t. If they can’t confirm, assume you need to handle it manually.

    One operator I work with migrated a 40,000-session-per-month site from shared hosting to BigScoots in June. They followed the 48-hour TTL reduction, kept the old account live for 36 hours post-migration, and saw zero crawl errors in Search Console. Organic traffic dipped 4% for two days—within normal daily variance—then returned to baseline. Total cost of the precaution: two extra days of overlap billing at $6. Cost of not doing it: potentially two weeks of suppressed rankings while Google re-crawls and re-establishes trust.

    If you’re planning a host migration in the next quarter, add “lower DNS TTL 48 hours early” to your runbook now. It’s the one step that prevents an invisible SEO penalty most operators don’t connect to hosting until it’s too late.

    Have a hosting or infrastructure question you’d like covered? Reply to this email—I read every one.

  • WordPress plugin auto-updates break staging—here’s the override

    WordPress plugin auto-updates break staging—here’s the override

    WordPress plugin auto-updates break staging—here's the override
    Photo by Fikret tozak on Unsplash

    WordPress auto-updates shipped as opt-in for plugins in 5.5, then flipped to opt-out for most managed hosts by 2025. The feature works—until you run a staging environment.

    The problem: auto-update preferences are stored in the database, not in code. When you enable auto-updates for a plugin on production, then clone your site to staging for testing, staging inherits that same setting. If staging pulls an update first and you later sync the database back to production, you’ve just pushed untested code live without realizing it.

    Most operators discover this after a layout breaks or a payment form stops submitting. The fix isn’t intuitive, because the WordPress dashboard shows auto-updates as a per-plugin toggle with no environment awareness.

    Where auto-update state lives

    Plugin auto-update preferences are stored in the wp_options table under the key auto_update_plugins. It’s a serialized array of plugin basenames. When you enable auto-updates for a plugin, WordPress adds its basename (e.g., akismet/akismet.php) to that array. When you clone a database, you clone that array.

    Managed hosts like WP Engine, Kinsta, and BigScoots run their own update schedules—usually twice daily. If your staging site is on the same host infrastructure and shares the same cron timing, it can pull updates before production does. The update itself isn’t the issue; it’s the accidental database sync afterward that surfaces the problem.

    This is distinct from WordPress core auto-updates, which are controlled by the AUTOMATIC_UPDATER_DISABLED and WP_AUTO_UPDATE_CORE constants. Those live in wp-config.php and can be set per environment. Plugin auto-updates don’t have an equivalent constant—yet.

    The config-level override

    You can disable plugin auto-updates entirely on staging using a filter in your theme’s functions.php or a custom plugin. Add this to your staging environment only:

    add_filter( 'auto_update_plugin', '__return_false' );

    This filter runs before WordPress checks the auto_update_plugins option, so it overrides any database settings. Your staging site will never auto-update plugins, even if the dashboard toggle is on. Production can still auto-update as configured.

    If you want more control—say, allow auto-updates for specific plugins on staging but block others—you can inspect the $update object passed to the filter:

    add_filter( 'auto_update_plugin', function( $update, $item ) {
      $allowed = [ 'akismet/akismet.php', 'hello-dolly/hello.php' ];
      return in_array( $item->plugin, $allowed );
    }, 10, 2 );

    This approach whitelists only the plugins you name. Everything else stays manual.

    The deployment risk most operators miss

    The inverse scenario is equally common: you disable auto-updates on production because you want full control, then push your database to staging for testing. Staging now also has auto-updates disabled—but you wanted staging to pull updates automatically so you could test them before manually applying to production.

    The cleanest fix is to treat auto-update state as environment-specific config, not content. That means:

    • Set the filter in code, per environment
    • Ignore the dashboard toggle, or document that it’s overridden
    • Never sync the auto_update_plugins option between environments

    If you’re using a database sync tool like WP Migrate or All-in-One WP Migration, add auto_update_plugins to your exclusion list. Most tools let you skip specific option keys during import.

    When auto-updates make sense

    For solo operators running a single production site with no staging, auto-updates work well for low-risk plugins: Akismet, Yoast SEO, contact forms. The risk is low because you’re already trusting the plugin author’s release process, and critical security patches ship faster than you’d apply them manually.

    For sites with custom plugins, membership logic, or payment processing, the calculus flips. An auto-update that changes a filter priority or deprecates a function can break checkout flows without warning. Staging exists to catch that—but only if staging doesn’t push updates back to production through an accidental database sync.

    The non-obvious tip: if you run multiple staging environments (e.g., one for content review, one for plugin testing), disable auto-updates on the content-review staging and enable them on the plugin-test staging. That way your content team never sees surprise layout changes, and your dev environment always has the latest code to test against.

    Want more WordPress operations breakdowns? Reply with the hosting or plugin behavior you want explained next—we cover one every Monday.

  • Stop paying for vanity analytics—track three metrics instead

    Stop paying for vanity analytics—track three metrics instead

    Stop paying for vanity analytics—track three metrics instead
    Photo: Saleemkce via Wikimedia Commons (CC BY-SA 4.0)

    If you’re running an online business solo or with a small team, there’s a good chance you’re paying for at least two analytics tools. Maybe Google Analytics for traffic, a heatmap service for behavior, and whatever your newsletter platform includes. You check them weekly, feel vaguely informed, and move on.

    Here’s the problem: most of those metrics don’t connect to money. Pageviews don’t pay invoices. Session duration doesn’t predict churn. Bounce rate tells you almost nothing about whether someone will subscribe, buy, or share.

    After working with dozens of operators who’ve scaled past $10k/month, the pattern is clear: the ones who move fastest track three metrics obsessively and ignore almost everything else.

    The three metrics that actually matter

    Metric one: new email subscribers per week. Not total list size—new additions. This number tells you whether your acquisition engine still works. If it drops two weeks in a row, you have a traffic problem, a conversion problem, or both. Track it in a spreadsheet, not buried in a dashboard. Write it down every Monday.

    Metric two: revenue per subscriber per month. Take last month’s revenue and divide by average list size. For a course creator with 2,000 subscribers who made $4,000 last month, that’s $2 per subscriber. For a sponsored newsletter with 8,000 readers earning $3,200, it’s $0.40. This number tells you whether you’re monetizing or just growing a list. If it’s under $0.50 and you’re trying to make this a business, you need to sell something.

    Metric three: unsubscribe rate per send. Not the pretty monthly average your ESP shows you—the raw number every time you hit send. ConvertKit, Beehiiv, and MailerLite all surface this in the broadcast report. If your rate jumps above 0.5% on a single send, you either wrote something polarizing (sometimes worth it) or your content drifted off-topic (never worth it). Track it per email, not per month, because monthly averages hide the problem sends.

    What to stop tracking

    Pageviews, unless you sell ads that pay CPM. Time on page, unless you’re debugging a specific UX problem. Heatmaps, unless you’re actively A/B testing a landing page this week. Social media follower count, unless a brand is paying you per impression and auditing your reach.

    These aren’t bad metrics. They’re just not decision metrics. They don’t tell you what to do next. And if a number doesn’t change your behavior, it’s decorative.

    The tool stack that actually works

    You don’t need a $500/month analytics suite to track three numbers. Here’s what works:

    • A spreadsheet. Google Sheets, Excel, Notion database—doesn’t matter. One row per week. Three columns. Update it Monday morning.
    • Your email platform’s native dashboard for subscriber and unsub data. You’re already paying for it.
    • A single revenue tracker. Stripe’s dashboard if you sell digital products. A bookkeeping tool like Wave (free) if you mix income sources. One source of truth for the revenue number.

    If you’re currently paying for Heap, Mixpanel, Hotjar, or a similar tool and you’re under $5k/month in revenue, cancel it. Put the $50–$200/month toward a better welcome sequence or a freelance editor. Those will move the three metrics. Another dashboard won’t.

    When to add a fourth metric

    Once you’re past $10k/month and you have a repeatable acquisition channel, you can afford to track one lever inside that channel. If SEO drives 60% of your traffic, track keyword rankings for your top ten posts. If Twitter drives your growth, track link clicks per post (not likes—clicks). If you run a paid funnel, track cost per subscriber.

    But don’t add a fourth metric until the first three are in a spreadsheet you update every week without thinking about it.

    Why operators resist this

    Cutting your analytics stack feels like flying blind. You’ll worry you’re missing something. You’re not. You’re missing noise.

    The operators who grow fastest are the ones who know their three numbers cold, can recite them in a conversation, and make every strategic decision by asking: “Will this move one of the three?”

    If the answer is no, they don’t do it. If the answer is yes, they do it this week.

    Want more operator tactics like this? Subscribe to One Two Three Send for weekly breakdowns of what actually works when you’re building an online business without a team.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • Productivity apps silently sync drafts across devices—and delete them

    Productivity apps silently sync drafts across devices—and delete them

    Productivity apps silently sync drafts across devices—and delete them
    Photo by charlesdeluvio on Unsplash

    You open your laptop to finish yesterday’s draft. It’s gone. Or worse: it’s there, but the last three paragraphs you wrote on your phone have vanished. The culprit isn’t user error—it’s how productivity apps handle sync conflicts when you edit the same document on two devices without waiting for the cloud to catch up.

    This happens more often than most solo operators realize, and the mechanics vary by app. Some tools silently overwrite. Others create duplicate conflicted copies you’ll never see unless you go looking. A few delete outright.

    How sync conflicts actually happen

    Most productivity apps—Notion, Obsidian, Apple Notes, Evernote, Bear—use eventual consistency models. When you edit a document on your phone, the app saves locally first, then pushes changes to the server when connectivity allows. If you open the same document on your laptop before that sync completes and start editing, both devices now hold divergent versions.

    What happens next depends on the app’s conflict-resolution logic:

    • Last write wins: The most recent save overwrites everything else. Apple Notes and Notion default to this. If your laptop autosaves two seconds after your phone, the phone edits disappear.
    • Conflicted copy creation: Obsidian and Evernote generate a duplicate file with a timestamp suffix (e.g., Draft (conflicted copy 2026-07-07)). The original keeps the laptop version. Your phone edits live in the copy—if you notice it exists.
    • Operational transformation: Google Docs and Dropbox Paper merge character-level changes in real time. This works well for collaborative editing but can still produce nonsense if two devices edit the same sentence simultaneously while offline.

    Notion’s block-based architecture adds a wrinkle. If you edit different blocks on different devices, they merge cleanly. Edit the same block, and last write wins for that block only. You can lose a paragraph while the rest of the page survives.

    When sync fails silently

    The worst-case scenario isn’t a visible conflict—it’s when the app gives no indication anything went wrong.

    Apple Notes, in particular, has a reputation for this. If you edit a note on your iPhone, lock the screen before it syncs (usually 5–10 seconds), then open the note on your Mac and keep typing, the Mac version often wins. The iPhone edits vanish with no warning, no conflicted copy, no recovery option unless you’ve enabled iCloud backups and know to check Recents.

    Obsidian with third-party sync plugins (Syncthing, Dropbox, iCloud Drive) can hit the same problem. If the file system syncs mid-save, you get a corrupted Markdown file—usually just the YAML frontmatter survives, and the body text turns into a jumble of merge markers. Obsidian’s built-in Sync service ($8/month for solo use) includes conflict detection, but the free version paired with file-based sync does not.

    How to avoid losing work

    The safest rule: never edit the same document on two devices within a 60-second window. Most apps sync within 10–30 seconds under good connectivity, but lag on slow networks or when backgrounded on mobile.

    Practical steps:

    • Wait for the sync indicator. Notion shows a small checkmark in the top right when saved. Obsidian’s Sync plugin shows a cloud icon. Apple Notes has no reliable indicator—assume 15 seconds minimum.
    • Search for “conflict” monthly. If your app creates conflicted copies, they pile up invisibly. Obsidian users can run a vault-wide search for conflict in filenames. Evernote buries them in the same notebook as the original.
    • Enable version history where available. Notion keeps 30 days of page history on the free plan (unlimited on paid). Obsidian Sync keeps 90 days. Apple Notes has no built-in versioning—use Time Machine or iCloud.com’s file recovery if you’re on Mac.
    • Draft in single-device contexts when stakes are high. If you’re writing a client proposal or a product launch email, keep it on one device until it’s done. The productivity gain from cross-device access isn’t worth the risk of losing three hours of work.

    The tools that handle this best (and worst)

    Google Docs remains the gold standard for conflict-free editing. Real-time operational transformation means you can edit on your phone, close it mid-sentence, open your laptop, and pick up exactly where you left off. The tradeoff: slower performance on long documents and no offline editing beyond basic text entry.

    Obsidian with paid Sync is the best option for Markdown users. Conflicts generate visible banners and preserve both versions. The $8/month cost is reasonable if you edit across three or more devices regularly.

    Apple Notes is the riskiest for operators who rely on it. No conflict detection, no version history you can trust, no export-and-compare workflow. If you use it, treat it as ephemeral—fine for grocery lists, bad for anything you can’t afford to lose.

    Notion splits the difference. Block-level merging works well most of the time, but when it fails, the lack of a conflicted-copy safety net means you’re dependent on page history. Check the changelog obsessively if you draft across devices.

    If you’ve lost work to sync conflicts in the past 90 days, reply and tell me which app and what happened. I’m collecting examples for a follow-up piece on recovery workflows.

  • ConvertKit vs. MailerLite vs. Brevo: which ESP for under 5,000 subscribers

    If you’re running a content business with fewer than 5,000 subscribers, your email platform choice matters more for cash flow than features. Most operators overpay for automation they don’t use, or underpay and hit walls when they need basic segmentation.

    Here’s how ConvertKit, MailerLite, and Brevo stack up when you’re still small enough that every $20/month counts.

    Pricing structure and breakpoints

    ConvertKit starts at $25/month for up to 1,000 subscribers on the Creator plan, jumping to $41/month at 1,500, then $66/month at 3,000. By 5,000 subscribers you’re paying $108/month. The free tier caps at 1,000 subscribers but strips out automation—useless if you’re trying to build evergreen onboarding sequences.

    MailerLite offers a free tier up to 1,000 subscribers with full automation included. Paid plans start at $10/month for 1,000, rising to $21/month at 2,500 and $32/month at 5,000. The pricing curve is gentler, and you keep all core features on the free plan.

    Brevo (formerly Sendinblue) bills by emails sent per month, not subscriber count. The free tier allows 300 emails/day—9,000/month. Paid plans start at $25/month for 20,000 emails. If you send weekly to 4,000 people, that’s 16,000 emails/month—you stay on the free plan. If you send daily, you’ll need paid. This model favors infrequent senders or operators with large lists who broadcast sparingly.

    Automation and segmentation depth

    ConvertKit’s visual automation builder is powerful but quirky. You can trigger sequences based on link clicks, tag applications, and custom field changes. The interface uses a node-based flowchart that gets messy past five branches. Segmentation works well—you can combine tags with custom fields using AND/OR logic.

    MailerLite’s automation editor is cleaner and faster to navigate. You get the same trigger options—email opens, link clicks, field updates—but the UI feels less cluttered. Segmentation is solid for basic use cases; advanced operators occasionally hit limitations when stacking multiple conditions with date-based rules.

    Brevo’s automation is the weakest of the three. You can build workflows, but the trigger options are limited compared to ConvertKit and MailerLite. Segmentation exists, but the interface is clunky. Brevo’s strength is transactional email and SMS—if you need those, it’s worth the automation trade-off. If you’re purely running a newsletter with welcome sequences, it’s less compelling.

    Deliverability and sending infrastructure

    All three platforms maintain strong sender reputations, but configuration matters. ConvertKit and MailerLite both enforce domain authentication (SPF, DKIM) and make setup straightforward. Brevo does the same but adds SMTP relay options if you want to route transactional mail separately from campaigns.

    Real-world deliverability is hard to benchmark because it depends on your list hygiene and engagement patterns. Operators report similar inbox rates across all three when lists are clean. The bigger risk is your sending behavior—if you import a cold list or blast infrequently, any platform will land you in spam.

    One edge case: MailerLite’s free tier includes its own branding in email footers unless you upgrade. ConvertKit and Brevo don’t add branding on free plans. If you’re staying free long-term, factor that in.

    Who each platform suits best

    Pick ConvertKit if you’re running a creator business with complex funnels—lead magnets feeding into paid courses, tag-based product recommendations, or multi-step nurture sequences. You’ll pay more, but the automation flexibility justifies it once you’re past 2,000 subscribers and actively monetizing.

    Pick MailerLite if you want full-featured email marketing without the ConvertKit premium. The free tier is legitimately usable, and the paid pricing scales gently. Best for newsletters, simple product launches, and operators who need automation but don’t want to spend $100/month yet.

    Pick Brevo if you send infrequently to a large list, need transactional email alongside campaigns, or want to add SMS down the road. The send-based pricing model is unusual but powerful for the right use case. Weakest choice if your primary need is sophisticated email automation.

    One thing to check before you commit

    All three platforms let you export your subscriber list as CSV, but automation export varies. ConvertKit and MailerLite let you duplicate and export sequences as templates. Brevo’s automation workflows don’t export cleanly—if you rebuild on another platform later, you’ll recreate them manually.

    If you’re just starting out and expect to migrate in 18 months, that’s not a dealbreaker. If you’re planning to stay put and scale, check the exit path before you build 20 automations.

    Want this kind of breakdown in your inbox? Subscribe to One Two Three Send for tool comparisons, pricing math, and operator-to-operator guidance every week.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • Newsletter platforms bill subscriber tiers in blocks—pay attention to the cutoff

    Newsletter platforms bill subscriber tiers in blocks—pay attention to the cutoff

    Newsletter platforms bill subscriber tiers in blocks—pay attention to the cutoff
    Photo by Markus Winkler on Unsplash

    If you’ve ever looked at your newsletter platform invoice the day after hitting 1,001 subscribers and wondered why your bill jumped $40, you’ve met block pricing. Most newsletter platforms don’t charge you per subscriber—they charge per tier, and each tier is a block.

    Cross the threshold by one subscriber, and you pay for the entire next block. The difference between 999 subscribers and 1,000 can be negligible. The difference between 1,000 and 1,001 can cost you an extra $30–$50 per month, depending on the platform.

    Here’s how block pricing works, where the expensive jumps happen, and what you can do about it.

    How newsletter platform pricing tiers actually work

    Most platforms structure pricing in blocks: 0–1,000 subscribers, 1,001–2,500, 2,501–5,000, and so on. You pay a flat rate for each block, regardless of whether you have one subscriber in that tier or five hundred.

    Take MailerLite’s pricing as an example. As of mid-2026, the jump from the 1,000-subscriber tier to the 2,500-subscriber tier increases your monthly cost from $15 to $29. If you hit 1,001 subscribers on the first day of your billing cycle, you pay $29 for the month—even though you’re only one subscriber over the line.

    Beehiiv follows a similar model. Their Scale plan covers up to 10,000 subscribers at $99/month. At 10,001, you move to the next pricing conversation—often custom, often significantly higher.

    ConvertKit’s tiers jump at 1,000, 3,000, 5,000, and 10,000. The shift from 1,000 to 3,000 subscribers takes you from $29/month to $49/month. You’re paying for capacity, not usage.

    The most expensive thresholds to watch

    Not all tier jumps cost the same. Some are minor bumps; others double or triple your bill.

    The 1,000-subscriber threshold is the first major jump for most solo operators. Platforms often offer generous free or low-cost tiers up to 1,000 subscribers, then increase pricing sharply. Crossing from 1,000 to 1,001 can take you from $10–$15/month to $25–$50/month depending on the platform.

    The 5,000-subscriber mark is another cliff. At this point, many platforms assume you’re monetising and have budget. Expect monthly costs in the $75–$150 range once you cross it.

    At 10,000 subscribers, several platforms (including Beehiiv) move you off public pricing entirely and into custom plans. This isn’t necessarily bad—you may get volume discounts—but it removes pricing transparency and adds negotiation overhead.

    Two strategies for managing block pricing

    You can’t avoid tier jumps forever, but you can control when they happen and reduce the sting.

    Audit and clean your list before crossing a threshold. If you’re sitting at 1,050 subscribers and approaching your billing renewal date, run a re-engagement campaign. Remove unengaged subscribers—those who haven’t opened in 90+ days. Depending on your list health, you might drop back under the threshold and stay in the lower tier for another month or two. This isn’t about gaming the system; it’s about paying only for subscribers who want to hear from you.

    Time your growth if you can. If you’re running a launch, promotion, or paid acquisition campaign that will push you over a tier threshold, schedule it right after your billing cycle renews—not right before. Crossing from 980 to 1,200 subscribers two days before renewal means you pay for the higher tier for nearly a full month while barely using the capacity. Crossing two days after renewal gives you the full month to grow into the new tier.

    When block pricing actually works in your favour

    Block pricing isn’t inherently bad. If you’re growing steadily within a tier, you’re effectively getting a volume discount—your per-subscriber cost decreases as you add people without crossing the threshold.

    For example, if you’re paying $29/month for up to 2,500 subscribers, your per-subscriber cost at 1,001 subscribers is $0.029. At 2,499 subscribers, it’s $0.012. You’re paying the same flat rate but serving more than double the audience.

    The key is to stay aware of where the cliffs are, plan your growth around them when possible, and keep your list clean so you’re not paying for dead weight.

    Want to compare platform pricing structures before you hit the next tier? Reply with the platform you’re on and your current subscriber count—I’ll flag the next threshold and what it’ll cost you.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • AI writing assistants cache your deleted drafts—here’s where

    AI writing assistants cache your deleted drafts—here’s where

    AI writing assistants cache your deleted drafts—here's where
    Photo by Towfiqu barbhuiya on Unsplash

    You write a draft in an AI-powered editor, decide it’s not working, hit delete, and move on. The text disappears from your screen. But in most cases, it’s still sitting on a server somewhere—sometimes for weeks, sometimes indefinitely.

    This isn’t a privacy scare piece. It’s a practical map of what actually happens to your writing when you use AI assistance, and what control you have over it.

    What gets cached and why

    AI writing assistants—whether standalone tools or features baked into editors—send your text to remote servers for processing. That’s how the model generates suggestions, rewrites, or completions. The question is what happens after.

    Most tools cache your input for at least two reasons: model improvement and abuse monitoring. OpenAI’s API retains inputs for 30 days by default unless you’re on a zero-retention enterprise plan. Anthropic’s Claude keeps data for 90 days for trust and safety review, then deletes it unless you opt into training (which is off by default for API users). Google’s Gemini API stores prompts for up to 48 hours for abuse detection.

    If you’re using a third-party tool that wraps one of these APIs—most AI writing assistants do—you’re subject to both the tool’s retention policy and the underlying model provider’s policy. A tool might delete your draft from its database immediately, but the API provider still has a copy for 30–90 days.

    What “delete” actually means

    Deleting a draft in your editor doesn’t usually trigger deletion on the backend. It removes the text from your view and maybe marks a database record as deleted, but the actual data often remains in backups, logs, or cached inference requests.

    Notion AI, for example, keeps deleted content in version history for 30 days. Jasper retains your documents on their servers indefinitely unless you manually delete your account. Most tools don’t surface this clearly—you have to dig into privacy policies or support docs.

    If you’re writing anything sensitive—client work, unpublished research, early-stage product positioning—treat “delete” as “hide from my dashboard,” not “erase from existence.”

    How to minimize exposure

    If retention matters for your use case, you have a few levers:

    • Use API-direct tools with zero-retention agreements. If you’re calling OpenAI or Anthropic’s API directly (or via a tool that passes through your own API key), you can request zero data retention. OpenAI offers this for API users who fill out a form; Claude offers it by default for paid API tiers. You lose some abuse protection, but your prompts aren’t stored.
    • Run local models. Tools like Ollama or LM Studio let you run open-weight models on your own hardware. Nothing leaves your machine. Performance lags behind frontier models, but for drafting or brainstorming, it’s often good enough.
    • Check whether the tool stores text or just metadata. Some AI features—like grammar checkers or readability scores—process text without sending full documents. Grammarly, for instance, sends sentences in chunks, not entire drafts, and claims not to store user content for training. That’s a smaller surface area than tools that upload whole documents.
    • Clear your account periodically. If you’re using a tool that keeps documents indefinitely, set a monthly reminder to delete old drafts. It’s manual, but it’s the only way to force removal in tools that don’t auto-expire content.

    When it actually matters

    For most solo operators writing blog posts or newsletters, cached drafts aren’t a real threat. The risk is low, and the convenience of AI assistance usually outweighs it.

    But if you’re drafting anything that could create liability—unreleased product specs, client strategy memos, legal documents, or anything under NDA—you need to know where your text lives and for how long. A 90-day retention window means a deleted draft from April is still on a server in July.

    The non-obvious move: use AI tools for generic scaffolding (outlines, headline variations, structural edits), then write the sensitive parts in a local text editor. You get the speed boost without the exposure.

    One Two Three Send covers the tools and tactics solo operators actually use. If this kind of breakdown is useful, subscribe—we publish daily.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.

  • WordPress full-page caching: when logged-in users break it

    WordPress full-page caching: when logged-in users break it

    WordPress full-page caching: when logged-in users break it
    Photo by Souvik Banerjee on Unsplash

    Most WordPress caching plugins promise faster page loads by storing static HTML and serving it to every visitor. That works beautifully—until someone logs in. Then the plugin faces a choice: serve the cached page and risk showing the wrong content, or bypass the cache entirely and slow the site back down.

    The default behavior varies wildly across plugins, and most solo operators don’t notice the problem until a reader reports seeing someone else’s dashboard, a broken checkout flow, or stale course-access gates.

    What full-page caching actually does

    Full-page caching generates a static HTML snapshot of each URL the first time someone visits it. Subsequent visitors get that snapshot instead of triggering PHP, database queries, and theme rendering. The speedup is dramatic—page load times drop from 800ms to under 100ms.

    But that snapshot is user-agnostic. It doesn’t know who’s viewing it. If the first visitor was logged out, the cached page shows a logged-out state. If you’re running a membership site, a course platform, or even just WordPress comments with reply threading, that’s a problem.

    Most caching plugins handle this by disabling the cache entirely for logged-in users. WP Rocket, W3 Total Cache, and WP Super Cache all do this by default. The moment you log in, you’re back to slow, uncached page loads.

    That’s fine if you’re the only one logged in. It’s not fine if you’re running a membership site with 500 active students, or a community forum where everyone has an account.

    The exceptions list: what to exclude

    Every caching plugin includes an exclude list—URLs or cookies that bypass the cache. The problem is that the defaults are conservative, and the documentation rarely explains why each rule exists.

    Here’s what typically needs exclusion:

    • Cart and checkout pages. WooCommerce, Easy Digital Downloads, and MemberPress all set cookies that modify page content. Cache those, and users see each other’s cart totals.
    • Account dashboards. Any page showing user-specific data—order history, profile settings, course progress—needs to bypass the cache.
    • Dynamic forms. Contact forms, quiz plugins, and conditional-logic forms often rely on nonces or session tokens. Cached nonces expire, and form submissions fail.
    • Personalized content blocks. If you’re using a plugin that shows different CTAs, testimonials, or upgrade prompts based on user role, those blocks need to load fresh.

    The tricky part: most plugins let you exclude by URL slug (/account/, /checkout/) but not by user role. That means you can’t serve cached pages to free members while bypassing the cache for paid members viewing the same URL.

    The two-tier workaround: fragment caching

    If you need fast page loads for logged-in users and personalized content, you need fragment caching—where parts of the page are cached, but user-specific elements load dynamically.

    This isn’t built into most full-page caching plugins. You need a CDN or a caching layer that supports Edge Side Includes (ESI) or a JavaScript-based approach where the page skeleton loads from cache and an AJAX call fetches user-specific content.

    Cloudflare Workers, Fastly, and some managed WordPress hosts (Kinsta, WP Engine) support ESI. For solo operators on shared hosting, the easier path is often to skip full-page caching for logged-in users entirely and optimize the uncached experience instead—faster database queries, lazy-loaded images, deferred JavaScript.

    Configuration that actually works

    Here’s a baseline exclude list for a typical membership or course site running on WordPress:

    • Any URL containing /my-account/, /dashboard/, or /profile/
    • Cart, checkout, and thank-you pages (plugin-specific slugs)
    • Any page using the wordpress_logged_in_* cookie
    • AJAX endpoints (/wp-admin/admin-ajax.php)
    • REST API routes serving dynamic data (/wp-json/ if you’re using it for frontend updates)

    Test this by logging in, visiting a cached page, and checking the HTTP headers. Look for X-Cache: HIT or X-Cache: BYPASS. If you see HIT on a page that should be personalized, add it to the exclude list.

    Most caching plugins also let you exclude by query string. If you’re running A/B tests or tracking UTM parameters, make sure those aren’t triggering separate cache entries—you’ll bloat storage and fragment your cache hit rate.

    One more thing: if you’re using a managed host with server-level caching, check whether their rules override your plugin settings. Kinsta and Flywheel both have their own caching layers that ignore plugin configurations. You’ll need to contact support or use their dashboard to adjust exclusions.

    Want more deep dives on the infrastructure behind online businesses? Subscribe to One Two Three Send—one focused article like this, delivered weekly.

  • Stripe Payment Links expire after inactivity—here’s the math

    Stripe Payment Links expire after inactivity—here’s the math

    Stripe Payment Links expire after inactivity—here's the math
    Photo by rupixen on Unsplash

    Stripe Payment Links are one of the fastest ways to collect money online. No custom checkout page, no embedded form, just a URL you drop into an email, a tweet, or a landing page. But there’s a catch most solo operators learn the hard way: Payment Links expire after 90 days of inactivity.

    Not 90 days from creation—90 days from the last completed transaction. If nobody buys through the link for three months, Stripe deactivates it. The URL still resolves, but customers see an error. No email notification. No dashboard warning. Just a dead link and lost revenue.

    How the expiration clock works

    Stripe Payment Links have two expiration modes: explicit and implicit. Explicit expiration is the one you set yourself—an end date or a maximum number of purchases. Implicit expiration is the 90-day inactivity rule, and it’s enabled by default on all Payment Links created after June 2025.

    The clock resets every time someone completes a purchase. If you sell one unit on day 89, the countdown starts over. But if your link sits unused for 90 consecutive days, it stops working. This affects evergreen products more than launches—if you’re selling a $50 course or a one-time audit and only move a few units per quarter, you’ll hit the limit.

    Stripe’s reasoning: unused links create support overhead and potential fraud exposure. Fair enough. But the lack of proactive alerts turns this into a silent failure.

    Where this breaks real workflows

    Payment Links show up in three common places: email sequences, social media bios, and static landing pages. If you’re running a welcome sequence that pitches a paid product on day 14, and that sequence hasn’t fired in three months because your list growth slowed, the link dies mid-funnel. Same for a Twitter bio link to a $20 template pack—if you don’t sell one every 90 days, it’s gone.

    The worst case: you’ve embedded the link in a PDF lead magnet or a YouTube video description. You can’t edit it after the fact. The only fix is to create a new Payment Link, update every instance, and hope you caught them all.

    Stripe’s dashboard doesn’t flag expired links in bulk. You have to open each one individually to check status. If you’re managing ten products across multiple Payment Links, that’s ten manual checks every quarter.

    How to prevent expiration without manual checks

    Three options. First, switch to Stripe Checkout Sessions via API. They don’t have the 90-day rule, but you lose the no-code convenience—you’ll need a server or a tool like Zapier to generate the session URL on demand.

    Second, use a redirect layer. Instead of linking directly to the Stripe Payment Link, use a short URL you control (Bitly, your own domain, whatever). When a Payment Link expires, you regenerate it in Stripe, then update the redirect target. Your public-facing URL never changes. This adds one extra HTTP request to the purchase flow, but it’s negligible.

    Third, set a calendar reminder to test-purchase through each Payment Link every 80 days. Use Stripe’s test mode if you want to avoid real charges, or complete a live transaction and immediately refund it. Not elegant, but it keeps the links active. If you’re running more than five products, this gets tedious fast.

    One thing that doesn’t work: adding the Payment Link to a Stripe Customer Portal. The expiration rule applies regardless of where the link lives. Same for embedding it in an iframe or wrapping it in a branded page. The 90-day countdown runs on Stripe’s side, not yours.

    What to do if a link already expired

    You can’t reactivate an expired Payment Link. You have to create a new one. Stripe preserves the product and price data, so it’s not a full rebuild—just a new link ID. But every external reference needs updating.

    Check your Stripe dashboard under “Payment Links” and filter by status. Expired links show as “Inactive.” If you find one, note where it was published: email sequences, social profiles, blog posts, PDFs, anywhere you dropped the URL. Then create the replacement and swap it in.

    For email sequences, this is straightforward if you’re using Beehiiv, MailerLite, or ConvertKit—edit the broadcast or automation step, replace the link, save. For static pages or social bios, same drill. For PDFs or videos, you’ll need the redirect-layer approach going forward.

    If you’re selling through multiple Payment Links and don’t want to babysit them, consider consolidating. One Payment Link per product is simpler to monitor than five variations for different traffic sources. Stripe’s analytics let you append UTM parameters to track source anyway, so you don’t lose attribution by using a single link.

    Bottom line: Stripe Payment Links are fast to set up, but they require maintenance. The 90-day inactivity expiration isn’t a bug—it’s policy. If you’re using them for evergreen products, build a check-in routine or switch to a URL structure you control. Otherwise, you’ll discover the problem when a customer emails to say your checkout is broken.

    Running a content-driven online business? One Two Three Send covers the tools, tactics, and infrastructure that solo operators actually use. Subscribe for weekly breakdowns—no fluff, just operator-to-operator details.

    Heads up — some links in this article are affiliate links. If you sign up through them, we may earn a small commission at no extra cost to you. We only recommend tools we use ourselves.