Author: onetwothreeadmin

  • Affiliate link management: when spreadsheets cost you money

    Affiliate link management: when spreadsheets cost you money

    Affiliate link management: when spreadsheets cost you money
    Photo by Gorilla ROI Data Connector on Unsplash

    If you run affiliate links across your content—newsletter, blog, social—you probably started with a spreadsheet. Product name, affiliate URL, commission rate, maybe a notes column. It works until it doesn’t.

    The breaking point isn’t volume. It’s versioning. Affiliate programs change their URLs, update terms, expire cookies faster, or shut down entirely. Your spreadsheet doesn’t tell you when a link dies. You find out three months later when a reader replies asking why your checkout link 404s.

    What breaks first

    Spreadsheets fail at three things: link rot detection, historical performance, and propagation speed.

    Link rot is silent. An affiliate program migrates to a new domain, updates their tracking parameter structure, or sunsets a product SKU. Your old link still resolves—it just doesn’t credit you. Unless you’re manually testing every link monthly, you won’t know.

    Historical performance matters when you’re deciding what to promote next quarter. A spreadsheet can log clicks if you’re using a link shortener with analytics, but matching clicks to actual conversions requires stitching together your shortener dashboard, the affiliate network backend, and your own notes. Most operators give up and optimize for vanity metrics instead.

    Propagation speed is the operational bottleneck. You update a link in your spreadsheet, then you have to manually find and replace it across every past article, email archive page, and pinned social post. If the link appears in 40 places, you’re burning an hour. If you skip the older posts, you’re leaving dead links live.

    When a link manager pays for itself

    Dedicated affiliate link management tools—Pretty Links, ThirstyAffiliates, Lasso—charge $10 to $30/month. The ROI threshold is straightforward: if one broken link costs you more than one month’s subscription in lost commissions, the tool pays for itself.

    For a solo operator earning $500/month in affiliate revenue, a single high-value conversion is worth $50 to $200 depending on the program. One missed sale covers six months of tooling.

    The feature that matters most isn’t the link cloaking or the pretty dashboard. It’s automatic redirect updating. You edit the destination URL once in the tool’s backend; every instance of that short link across your entire site updates instantly. No find-and-replace. No archaeology through old posts.

    Link health monitoring is the second-order benefit. Tools like Lasso ping your affiliate URLs weekly and flag 404s or redirects that don’t resolve to the expected domain. You get an alert, fix it, move on. The alternative is discovering the problem when a reader emails you or when you notice commission drops in your next payout statement.

    The spreadsheet-plus-shortener hybrid

    If you’re not ready to pay monthly, the middle path is a spreadsheet plus a custom domain short link service. Rebrandly’s free tier gives you 500 branded links and click tracking. You store the short link in your spreadsheet, paste that short link everywhere, and update the destination URL in Rebrandly when the affiliate program changes.

    This works if you have fewer than 50 active affiliate relationships and you’re disciplined about logging every new link. It breaks when you forget to add a link to the sheet, or when you need to bulk-edit links by category (“update all Amazon links to the new Associate ID”).

    The hidden cost is context switching. Every time you create a new affiliate link, you’re opening three tabs: the affiliate dashboard to generate the URL, Rebrandly to shorten it, and your spreadsheet to log it. That’s 90 seconds per link. If you’re adding 10 links a week, that’s 15 minutes weekly—13 hours a year—on administrative overhead.

    What to do Monday

    Audit your last 90 days of affiliate links. Open your spreadsheet, click every URL, and verify it resolves to the correct product page with your tracking parameter intact. If more than 10% are broken or redirect incorrectly, you have a link rot problem worth solving.

    If you’re earning less than $200/month in affiliate revenue, stay with the spreadsheet but set a calendar reminder to re-check links quarterly. If you’re above $500/month or managing more than 30 active programs, trial a link manager for one month and measure time saved on link updates.

    The goal isn’t perfect tracking. It’s reducing the lag between when a link breaks and when you notice. Every day a broken link stays live is a day you’re sending traffic you can’t monetize.

    One Two Three Send covers the tools and tactics solo operators actually use to run content businesses. Subscribe to get one focused article daily—no filler, no fluff.

  • Canva’s Magic Resize: when aspect-ratio automation saves time vs. breaks it

    Canva’s Magic Resize: when aspect-ratio automation saves time vs. breaks it

    Canva's Magic Resize: when aspect-ratio automation saves time vs. breaks it
    Photo: Bystronic Corporate Communications via Wikimedia Commons (CC BY-SA 4.0)

    Canva’s Magic Resize feature promises to turn one social graphic into ten platform-ready versions with a single click. You design once at 1080×1080, hit resize, select Instagram Story + LinkedIn post + Pinterest pin, and the tool redistributes text boxes, images, and spacing to fit each canvas.

    It works exactly as advertised—when your design is simple. Two text blocks, a centered logo, and a background gradient? Magic Resize handles it cleanly. But stack five text layers with custom positioning, overlay transparent PNGs, or use grouped elements with manual kerning, and you’ll spend more time fixing the output than you would rebuilding from scratch.

    How Magic Resize decides what moves

    Magic Resize uses a hierarchy system. Canva prioritizes foreground elements (text boxes, stickers, uploaded images) over background layers. When you switch from a 1:1 square to a 9:16 Story canvas, the tool expands the vertical space and redistributes elements top-to-bottom based on their original layering order.

    Text boxes resize proportionally by default—font size stays fixed, but line breaks reflow to fit the new width. Images scale to maintain aspect ratio. Background fills stretch to cover the entire canvas without cropping.

    The problem: Canva doesn’t understand visual hierarchy the way you do. If your Instagram square placed a call-to-action at the bottom because that’s where the eye naturally lands in that format, Magic Resize will keep it at the bottom of a tall Story canvas—where it’s offscreen until someone swipes up.

    Grouped elements break the logic entirely. If you’ve grouped a text box with a shape to create a custom badge, Magic Resize treats the group as a single object and scales it proportionally. A badge that was 15% of your square design becomes 15% of your Story height—often way too large or positioned awkwardly.

    When to use it vs. when to duplicate manually

    Magic Resize works best for templated content where layout consistency matters more than pixel-perfect positioning. Weekly quote graphics, announcement cards, course promotional images—anything with one dominant message and minimal layering.

    Skip it when:

    • Your design uses more than four text layers with custom positioning
    • You’ve applied manual spacing or alignment that depends on the original canvas shape
    • Grouped elements make up more than 30% of the design
    • You’re resizing from a horizontal format (16:9 YouTube thumbnail) to vertical (Pinterest pin)—the text reflow often breaks readability

    For complex designs, duplicate the original file instead. Canva lets you copy an entire design and manually adjust the canvas dimensions. You’ll spend three minutes repositioning elements yourself, but you’ll have full control over what moves and what scales.

    The non-obvious tip: pre-size your text boxes

    Most operators let Canva auto-size text boxes—you type, the box expands to fit, and you drag it into place. That approach breaks Magic Resize because the tool doesn’t know which dimension (width or height) you prioritized.

    Instead, manually set text box dimensions before you type. Click the text box, drag it to a fixed width (say, 800 pixels on a 1080-wide canvas), then type your headline. Lock the width in place. When Magic Resize redistributes the layout, it preserves your width ratio and reflows text vertically—keeping line breaks predictable.

    Same goes for images. If you upload a logo or product shot, resize and position it first, then lock the layer. Magic Resize respects locked elements and works around them, giving you anchor points that stay consistent across formats.

    Pricing and access

    Magic Resize is available on Canva Pro ($15/month for solo users, $30/month for up to five team members) and Canva for Teams plans. The free tier doesn’t include it—you’ll need to manually duplicate and resize instead.

    If you’re publishing to three or more platforms weekly and your designs stay simple (under five layers, minimal grouping), the feature pays for itself in saved time. If your graphics are layout-heavy or require tight control over spacing and alignment, the Pro subscription still has value for the template library and Brand Kit features, but Magic Resize won’t be the reason you renew.

    Want more tool breakdowns like this? Subscribe to One Two Three Send and get operator-focused features, comparisons, and how-tos every week—no fluff, just the details that matter when you’re running a content business solo.

  • WordPress transactional email: when wp_mail() fails silently

    WordPress transactional email: when wp_mail() fails silently

    WordPress transactional email: when wp_mail() fails silently
    Photo by Mariia Shalabaieva on Unsplash

    WordPress sends password resets, comment notifications, and form submissions through a single PHP function: wp_mail(). It works—until it doesn’t. And when it breaks, you usually won’t know.

    There’s no delivery confirmation, no bounce handling, no retry logic. The function returns true if it handed the message to your server’s mail transport. What happens after that is invisible.

    For solo operators running contact forms, membership sites, or order confirmations, silent email failure costs conversions and creates support overhead. Here’s when the built-in system breaks, what to replace it with, and how to make the switch without touching every plugin individually.

    When wp_mail() actually breaks

    WordPress uses your server’s local mail transfer agent by default—usually Sendmail or Postfix. Shared hosting providers throttle or block outbound SMTP to prevent spam. Budget VPS instances often ship with no MTA configured at all.

    Even when mail leaves your server, deliverability suffers. Your domain lacks proper SPF and DKIM records for server-originated mail. Gmail and Outlook route it to spam or reject it outright. You’ll never see the bounce.

    Common failure scenarios:

    • Password reset emails never arrive, users assume the form is broken
    • WooCommerce order confirmations vanish, customers contact support
    • Gravity Forms or Contact Form 7 submissions disappear after the success message
    • Comment reply notifications stop working, engagement drops

    The function still returns true. WordPress has no idea delivery failed.

    Replace wp_mail() with an SMTP plugin or API bridge

    You need to route WordPress mail through a transactional email service with proper authentication and delivery tracking. Two approaches work:

    SMTP plugins reconfigure wp_mail() to connect to an external mail server. WP Mail SMTP (free) and Post SMTP (free) both support Gmail, SendGrid, Mailgun, and Amazon SES. You add credentials, test a message, and every plugin that calls wp_mail() automatically routes through the new transport.

    Setup takes ten minutes. The catch: SMTP connections can time out under load, and you’re still managing API keys in the WordPress admin.

    API-based plugins replace the SMTP handshake with HTTP calls. Postmark’s official plugin (free) and Mailgun’s plugin both inject an API bridge. Delivery is faster, retries are automatic, and you get real bounce logs in the service dashboard.

    For solo operators sending under 1,000 transactional emails per month, Postmark’s free tier covers password resets and form notifications. Once you cross 1,000 sends, pricing starts at $10/month for 10,000 emails—still cheaper than the support time spent debugging silent failures.

    One non-obvious configuration detail

    After you install an SMTP or API plugin, set a dedicated “From” address and verify it with your email service. Most plugins default to [email protected], which triggers spam filters if that address doesn’t exist or lacks DNS records.

    Create [email protected] or [email protected] as a real mailbox (or alias), add it to your transactional service’s verified sender list, and configure the plugin to use it. This single step fixes 80% of residual deliverability problems after switching away from wp_mail().

    Also: enable logging in the plugin settings. WP Mail SMTP and Post SMTP both include email logs that show exactly what fired, when, and to whom. When a customer says they didn’t get a receipt, you’ll know whether it was sent.

    When to stay with wp_mail()

    If you’re running a single-author blog with comments disabled and no forms, the built-in function is fine. You’re only sending password resets to yourself, and you’ll notice if those break.

    But the moment you add a contact form, membership plugin, e-commerce checkout, or any user-triggered email, the risk shifts. Silent failure becomes a business problem, not a technical curiosity.

    Switching to a transactional service doesn’t require a developer. Install a plugin, add an API key, send a test. If the test arrives and your logs confirm it, you’re done.

    What’s breaking on your WordPress site right now? Hit reply and tell us which email mystery you’ve been ignoring. We’ll cover it in a future piece.

  • AI writing assistants charge per seat—when to share logins instead

    AI writing assistants charge per seat—when to share logins instead

    AI writing assistants charge per seat—when to share logins instead
    Photo by Emil Karlsson on Unsplash

    AI writing tools have adopted SaaS pricing: one seat, one user, one monthly fee. Add a second person—a contract editor, a VA who schedules posts, a designer who needs context—and you’re suddenly paying double.

    For solo operators who occasionally collaborate, that math doesn’t work. You’re not running a newsroom. You don’t need role-based permissions, audit logs, or centralised billing. You need someone to proofread a draft on Tuesday and disappear until next month.

    Most AI platforms don’t want you sharing logins, but the pricing gap between individual and team plans creates a structural mismatch for small operations. Here’s when sharing credentials makes operational sense, and when you actually need to pay for seats.

    When shared logins work fine

    If your collaborator needs access fewer than five times a month, and you’re not working in the tool simultaneously, a shared login handles it. One operator I talked to shares her Claude account with a contract editor who fact-checks newsletter drafts twice a week. The editor logs in, opens the shared thread, leaves comments, logs out. Total time: under an hour per session.

    The workflow constraint is synchronous conflict. If you’re both drafting in the same thread at 9am, someone’s work gets overwritten. For async handoffs—”I drafted this, you edit it by Thursday”—shared access works.

    Most AI tools don’t enforce device limits or concurrent session blocks on individual plans. ChatGPT Plus, Claude Pro, and Jasper’s Starter tier all allow login from multiple devices without flagging the account. They assume you’re switching between your laptop and phone, but the technical guardrail is the same.

    When you need to pay for seats

    Team plans make sense when you need simultaneous access, conversation history separation, or compliance coverage. If you’re working in the tool at the same time—co-editing a product launch sequence in real time—shared credentials break down. You’ll overwrite each other’s changes or lock each other out mid-session.

    Conversation history is the other friction point. Shared logins mean shared threads. If your VA is using the account to draft social captions while you’re debugging a landing-page headline, your chat history turns into an unnavigable mess. Finding yesterday’s draft means scrolling past twenty unrelated threads.

    Some platforms offer workspace separation on team plans. Jasper’s Business tier gives each user isolated project folders. ChatGPT Team lets you create shared spaces without bleeding personal threads into the company view. If you’re collaborating weekly or more, that structure is worth the seat cost.

    Compliance matters if you’re handling customer data or operating in a regulated niche. Shared logins muddy accountability—your Terms of Service violation could be your editor’s mistake, but the platform sees one account. Team plans with per-user audit trails give you a paper trail if something breaks.

    Pricing breakpoints that matter

    Claude Pro costs $20/month for individuals. Claude Team starts at $30/month per seat, minimum two seats, so $60/month total. If your editor logs in twice a month, you’re paying $40/month for convenience features you don’t use.

    ChatGPT Plus is $20/month individual, $25/user/month for teams (minimum two users, so $50/month). The team plan adds shared conversation history and admin controls. For occasional collaboration, that’s $30/month you’re spending to avoid saying “log out when you’re done.”

    Jasper starts at $39/month for individuals (called Creator), then jumps to $99/month for Teams. The gap is wide enough that most solo operators share logins until they’re collaborating daily.

    The tipping point isn’t about budget—it’s about friction cost. If you’re losing twenty minutes a week to login coordination, thread archaeology, or overwritten drafts, the team plan pays for itself. If you’re handing off async once a week with zero conflicts, keep sharing.

    The tool doesn’t care—until it does

    AI platforms bury account-sharing language in their Terms of Service, but enforcement is rare for individual-tier plans. They’re optimised to catch resellers and abuse (one account serving a dozen users), not a solo operator splitting access with a part-time editor.

    That said, if you’re logging in from different cities on the same day, or running hundreds of queries in parallel, you risk a flag. The platform sees usage patterns, not intent. Keep activity reasonable—if it looks like one person’s workload, you’re fine.

    One non-obvious risk: password resets. If your collaborator changes the password and forgets to tell you, you’re locked out mid-project. Set up a shared password manager (1Password, Bitwist) so credentials live in one auditable place, not a text thread.

    If you’re already running a team plan for other tools, check whether your AI assistant offers bundled pricing. Some operators I know share a ChatGPT Team account purely because they were already paying for shared Notion and Figma—it’s one less login to manage.

    Want more operator-level breakdowns of tools, pricing, and workflows that actually matter? Subscribe to One Two Three Send for weekly deep-dives into the small decisions that compound.

    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 archive search: when readers can’t find what you wrote

    Newsletter archive search: when readers can’t find what you wrote

    Newsletter archive search: when readers can't find what you wrote
    Photo: Unknown via Wikimedia Commons (Public domain)

    A reader emails: “I know you wrote about WordPress caching last month—where is it?” You know you sent it. You can see it in your sent folder. But when they search your archive page, nothing turns up.

    Archive search is one of those features newsletter platforms advertise but rarely explain. Some index subject lines only. Others index the first 200 characters. A few index the full body—but only if you’re on a paid tier. And almost none tell you which approach they use until you test it yourself.

    Here’s what actually gets indexed on the platforms solo operators use most, and what to do when search fails.

    What gets indexed on each platform

    Beehiiv indexes the full email body on all tiers, including free. Search works across subject lines, body text, and author names if you’ve enabled bylines. The index updates within a few minutes of sending. One caveat: if you use custom HTML blocks, only plain text inside those blocks gets indexed—images, buttons, and styled div containers are ignored.

    Substack indexes subject lines and body text, but search results prioritize exact matches in titles first. If your subject line was vague (“Issue #47”) and the meat of the topic is buried in paragraph three, it won’t surface until a reader scrolls past a dozen other posts. Substack’s archive search also doesn’t support Boolean operators—no “AND,” “OR,” or quoted phrases.

    ConvertKit offers archive search only if you’ve enabled the public archive feature, which is off by default. When enabled, it indexes subject lines and the first 500 characters of body text. Anything below the fold in your email—your detailed how-to, your step-by-step breakdown—doesn’t get indexed. If you bury the lede, readers won’t find it.

    MailerLite doesn’t offer built-in archive search at all. The public archive page displays a reverse-chronological list with subject lines and send dates. Readers have to use browser find (Cmd+F) and hope the subject line matches what they remember. For a catalog of 50+ emails, that’s borderline unusable.

    When to use tags and categories instead

    If your archive grows past 30 posts, search alone won’t save readers. They need filters—by topic, by format, by content type. Beehiiv lets you tag posts and surface those tags as filters on your archive page. Substack offers Sections, which let you split your newsletter into topic-based streams (each with its own archive and RSS feed).

    ConvertKit doesn’t support tags or categories in the public archive view. If you need taxonomy, you’ll need to maintain a separate landing page with manual links—or migrate to a platform that supports it natively.

    The non-obvious move: if you publish consistently on a topic (say, WordPress hosting or AI prompts), create a dedicated landing page that lists all related posts with short descriptions. Link to it from your welcome email and your site nav. That page becomes your real archive. The platform’s built-in search becomes a backup.

    What breaks when readers search from mobile

    Most newsletter platforms serve the same archive page to mobile and desktop, but mobile browsers handle search differently. Safari on iOS doesn’t support in-page search widgets that rely on JavaScript—if your platform uses a custom search bar (instead of a plain HTML form), iOS readers get a broken experience. They tap the search icon, nothing happens, and they leave.

    Beehiiv and Substack use standard HTML forms, so mobile search works. ConvertKit’s archive search widget relies on JavaScript and fails silently on older mobile browsers. MailerLite, again, offers no search at all.

    Test your archive page on an actual phone, not just a resized browser window. Open it in Safari, Chrome, and Firefox mobile. Try searching for a post you know exists. If the search bar doesn’t respond or returns zero results for a term you know is there, your readers are hitting the same wall.

    When to embed a third-party search tool

    If your archive has 100+ posts and your platform’s search isn’t cutting it, you can embed a third-party site search tool. Algolia offers a free tier for up to 10,000 searches per month. You’ll need to generate a JSON feed of your archive (most platforms support RSS; convert it to JSON with a script or a tool like Feed43), push it to Algolia’s index, and embed their search widget on a custom landing page.

    This works if you host a separate website alongside your newsletter (common for operators who publish on Substack but maintain a WordPress site for SEO). It doesn’t work if you rely solely on the platform’s hosted archive—Substack and Beehiiv don’t let you inject third-party JavaScript into their archive pages.

    The simpler fix: write better subject lines. If every email is titled “Weekly Update” or “Issue #23,” no search tool will help. Use the subject line to signal the topic clearly. “WordPress object caching: Redis vs. memcached” beats “Performance tips” every time.

    Want more tool breakdowns like this? Subscribe to One Two Three Send and get one operator-focused deep-dive every day—no fluff, just what actually works and what breaks.

    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.

  • Notion databases as CRMs: when it breaks and what to use instead

    Notion databases as CRMs: when it breaks and what to use instead

    Notion databases as CRMs: when it breaks and what to use instead
    Photo: Saumya Singh 06 via Wikimedia Commons (CC BY-SA 4.0)

    Notion databases feel like the perfect CRM when you’re managing your first dozen sponsor contacts or affiliate relationships. Drag a card, add a relation, filter by status—it’s visual, it’s flexible, and it’s already part of your workspace.

    Then you hit 200 contacts. Or you need to send 40 follow-up emails in one afternoon. Or you want to see which sponsors opened your pitch. That’s when the cracks show.

    Notion wasn’t built to be a CRM. It was built to be a database interface inside a document editor. The distinction matters more than most solo operators realise until they’re deep enough in that migrating feels painful.

    Where the Notion database model fails

    The first breaking point is bulk actions. Notion lets you select multiple database entries and change a single property—status, tag, date. But if you need to update five fields across 30 records, or send templated emails to a filtered segment, you’re clicking into each row one by one.

    There’s no native way to trigger an action when a property changes. You can’t auto-send a follow-up email when a sponsor moves to “Negotiating,” or log a timestamp when a contact replies. Zapier can bridge some of this, but you’re bolting automation onto a tool that doesn’t expose the hooks a real CRM would.

    Search breaks down fast. Notion’s database search works within a single view at a time, and it’s not full-text across linked databases. If you’ve split your sponsor contacts, media kit versions, and pitch history into separate tables—like Notion best practices suggest—you can’t search across all three and get a unified contact timeline.

    Permissions get messy when you bring on a contractor or co-founder. Notion’s sharing model is page-level. You can’t give someone access to sponsor contacts without also giving them access to the parent page, which might include financials, drafts, or unrelated projects. Real CRMs let you control visibility at the record or field level.

    When Notion is still the right call

    If you’re managing fewer than 100 contacts, aren’t doing daily outreach, and don’t need email tracking or automation, Notion’s database is fine. It’s especially good if your CRM needs overlap heavily with project documentation—keeping pitch decks, negotiation notes, and contract PDFs in the same workspace where you track the relationship.

    Notion also works when your “CRM” is really just a lead list. If you’re sourcing potential sponsors from a directory, tagging them by fit, and handing off the actual outreach to a platform like Mailshake or Lemlist, Notion can serve as the pre-CRM layer without strain.

    What to use when you outgrow it

    Most solo operators don’t need Salesforce. You need something that handles contact records, email sequences, and basic pipeline tracking without a multi-week setup.

    Brevo (formerly Sendinblue) includes a lightweight CRM alongside its email platform. You get contact records, deal pipelines, and the ability to trigger email automation when a deal stage changes. Pricing starts free for up to 300 emails per day, and the CRM features are included even on the free tier. It’s a good fit if your CRM is primarily for sponsor or affiliate outreach and you want email tracking built in.

    Airtable sits between Notion and a real CRM. It’s still a database tool, but it has better bulk-edit controls, more powerful filtering and grouping, and a cleaner API if you’re connecting it to Zapier or Make. The interface feels more like a spreadsheet than a document, which some operators prefer once contact volume climbs. The free tier caps at 1,000 records per base.

    Streak lives inside Gmail and turns your inbox into a CRM. Each contact thread becomes a pipeline card. You can see open rates, set reminders, and log notes without leaving your email client. It’s $15/month for the solo plan and works well if most of your relationship management happens over email. The tradeoff: no standalone contact view outside Gmail, so reporting and bulk edits are limited.

    Migration friction is real—plan for it early

    The hardest part of moving off Notion isn’t picking the next tool. It’s extracting your data without breaking relationships between records. Notion’s CSV export flattens relations into plain text, so if you’ve linked sponsor contacts to pitch history or media kits, those connections don’t survive the export.

    If you’re at 80 contacts and starting to feel the friction, that’s the time to move—not at 300 when you’ve got two years of notes embedded in linked databases. Set aside an afternoon, export your main contact table, and rebuild the essentials in the new tool. Don’t try to migrate every field or historical note. Carry forward active contacts, current pipeline deals, and the last six months of interaction history. Archive the rest in Notion as read-only reference.

    The goal isn’t to find the perfect CRM. It’s to use a tool that doesn’t force you to work around its limitations every time you need to do something twice.

    Reply with the tool you’re using to manage sponsors, affiliates, or client contacts—I’m tracking what solo operators are actually reaching for in 2026.

    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.

  • Traffic spikes don’t convert when site infrastructure chokes

    Traffic spikes don’t convert when site infrastructure chokes

    Traffic spikes don't convert when site infrastructure chokes
    Photo by Denys Nevozhai on Unsplash

    A Reddit thread mentions your post. A newsletter with 40,000 subscribers links to your landing page. Traffic jumps from 200 daily visitors to 4,000 in two hours.

    Then your site slows to a crawl. Checkout forms time out. Signups fail silently. By the time you notice, the spike is over—and conversion rate sits at 0.3% instead of the usual 4%.

    Traffic spikes expose infrastructure weaknesses that low-volume days hide. If your hosting, caching, and checkout stack can’t handle sudden load, you’re paying for traffic that evaporates before it converts.

    Where the bottlenecks actually are

    Most operators assume their hosting plan is the problem. Sometimes it is—shared hosting with 512MB RAM caps will buckle under 2,000 concurrent visitors. But more often, the issue is uncached database queries on key pages.

    Your homepage might load fine. Your blog archives might be fully cached. But your pricing page, your checkout flow, and your signup form often bypass page caching entirely because they’re dynamic or session-dependent.

    When traffic surges, those pages hammer your database. MySQL max connections gets exhausted. PHP workers queue. Page generation time climbs from 400ms to 8 seconds. Visitors see spinning loaders, then leave.

    The fix: enable object caching (Redis or Memcached) and audit which pages are hitting the database on every load. Use query monitoring plugins to log slow queries during normal traffic, then optimize or cache those before the next spike.

    Checkout flows fail under load differently than content pages

    A slow blog post is annoying. A slow checkout is revenue lost.

    Payment processors like Stripe have API rate limits. If 300 people try to check out simultaneously and your site fires a Stripe API call on every page render (not just on final submit), you’ll hit rate limits and see cryptic errors instead of completed purchases.

    Similarly, if your checkout page includes external scripts—analytics pixels, chat widgets, recommendation engines—each one adds latency. During a traffic spike, third-party script timeouts compound. The page technically loads, but the purchase button doesn’t render or doesn’t respond.

    Strip checkout and signup flows to the minimum. Lazy-load or async-load everything non-critical. Test with browser dev tools throttled to “Slow 3G” and simulate 50 concurrent sessions using a load-testing tool like Apache Bench or k6.

    CDN and edge caching only work if configured correctly

    Turning on a CDN doesn’t automatically cache everything. Most CDNs respect your origin server’s cache headers. If your WordPress install sends Cache-Control: no-cache on key pages, the CDN won’t cache them.

    Check your CDN’s cache hit rate during normal traffic. If it’s below 70%, you’re serving most requests from origin—which means a traffic spike still hits your server directly.

    Set explicit cache rules at the CDN level for static assets, blog posts, and any page that doesn’t change per user. Use cache keys carefully: if your CDN caches by full URL including query parameters, every UTM-tagged inbound link creates a separate cache entry, and you lose the benefit entirely.

    What to do before the next spike

    Run a load test. Use a tool like Loader.io or k6 to simulate 1,000 concurrent users hitting your highest-value pages: homepage, top blog post, pricing page, signup form, checkout.

    Watch server CPU, memory, and database connection count in real time. Identify the breaking point. If your site starts timing out at 800 concurrent users, you know your ceiling.

    Then fix the biggest bottleneck: upgrade hosting if you’re on shared; enable object caching if you’re on WordPress; strip third-party scripts from conversion pages; set aggressive CDN cache rules for static content.

    Test again. Measure the new ceiling. Repeat until you can handle 3–5x your normal peak traffic without degradation.

    Traffic spikes are rare, but they’re also your highest-leverage moments. A single viral post or newsletter mention can bring a month’s worth of visitors in a day—but only if your infrastructure can convert them.

    Want more operator tactics like this? Subscribe to One Two Three Send for weekly deep-dives on the tools, tactics, and infrastructure behind sustainable online businesses.

  • Instagram Broadcast Channels: how the one-way DM feature works

    Instagram Broadcast Channels: how the one-way DM feature works

    Instagram Broadcast Channels: how the one-way DM feature works
    Photo: ЗАО «Азия Ритейл» via Wikimedia Commons (CC BY 4.0)

    Instagram Broadcast Channels are a one-to-many messaging feature that lives inside Direct Messages. You send updates, photos, polls, or voice notes to subscribers who’ve opted in—but they can’t reply directly to the group. Only you can broadcast; they can react with emojis or reply privately to you.

    It’s not a feed post, not a Story, and not a newsletter. It’s a notification-driven channel where every message hits your subscribers’ DM inbox with a push alert, assuming they haven’t muted you.

    How it works

    You create a Broadcast Channel from your Instagram profile or DM screen. Give it a name, pick an audience (everyone or paid subscribers only, if you have subscriptions enabled), and start sending. Subscribers join by tapping a link you share in Stories, posts, or your bio.

    Messages you send appear in chronological order. Subscribers see them in their DM list, alongside regular conversations. There’s no algorithmic feed here—what you send is what they see, in order.

    You can send text, photos, videos up to 60 seconds, voice notes, and polls. Links work. You can also share posts from your feed or others’ accounts directly into the channel. Subscribers can react with emoji, and you’ll see a count, but they can’t post their own messages to the group.

    If a subscriber wants to reach you, they send a separate private DM. The channel itself stays one-directional.

    When to use it

    Broadcast Channels make sense when you want direct reach without depending on the feed algorithm, but you’re already building an audience on Instagram. Think of it as an owned notification channel inside a rented platform.

    Operators use them for:

    • Quick updates: Product drops, new post alerts, schedule changes. Faster than Stories, more direct than a feed post.
    • Exclusive previews: Behind-the-scenes content, early access to links, or subscriber-only commentary on news in your niche.
    • Community engagement without moderation overhead: Unlike a group chat, you’re not managing dozens of replies or off-topic threads. Subscribers react, you move on.
    • Driving traffic off-platform: Share a link to your latest article, course launch, or affiliate review. The push notification increases click-through compared to a bio link.

    It’s not a replacement for email. Instagram controls delivery, and subscribers can leave or mute without you knowing immediately. But if your audience lives in DMs and you’re already posting daily, it’s a low-friction way to add a direct line.

    The non-obvious tip: use polls to surface reply-worthy topics

    Broadcast Channels don’t allow group replies, but subscribers can DM you privately. Most won’t—unless you give them a reason.

    Here’s the trick: use polls not just for engagement metrics, but to identify high-interest topics, then explicitly invite private replies on the winner.

    Example: you run a course-creation business. Send a poll: “Next tutorial—email sequence breakdowns or sales page teardowns?” Once results come in, follow up with: “Sales page teardowns won. If you’ve got a page you want reviewed, DM me the link—I’ll pick one for Friday’s breakdown.”

    This does two things. First, it turns a passive poll into a conversation starter. Second, it fills your DM inbox with qualified leads or content ideas without you fishing for them in comments.

    The same tactic works for product feedback, topic requests, or case study volunteers. Polls lower the friction to signal interest; the follow-up prompt converts that interest into a direct message you can act on.

    Limits and gotchas

    Instagram doesn’t publish a hard subscriber cap for Broadcast Channels, but the feature is designed for creators with established audiences—you need a Creator or Business account to start one.

    Messages you send are permanent until you delete them. Subscribers can screenshot anything. Treat it like public content, even though it feels private.

    There’s no built-in analytics dashboard. You’ll see reaction counts and poll results, but Instagram doesn’t show you open rates, click-through on links, or subscriber growth over time. You’re flying partially blind compared to email platforms like Postmark or MailerLite, where delivery and engagement metrics are standard.

    If you’re juggling Instagram Broadcast Channels alongside other social platforms, tools like Publer can centralise your scheduling workflow—though Broadcast Channel messages themselves still need to be sent manually from the Instagram app.

    One more thing: subscribers don’t get a digest. Every message you send triggers a separate notification. Send too often, and they’ll mute or leave. There’s no research-backed frequency ceiling, but operators I’ve talked to stick to 2–4 messages per week unless they’re running a time-sensitive campaign.

    If you’re testing Broadcast Channels or have questions about balancing Instagram and email, reply to this issue—I read every message and often turn good questions into future breakdowns.

    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 object caching: when to enable Redis and when memcached wins

    WordPress object caching: when to enable Redis and when memcached wins

    WordPress object caching: when to enable Redis and when memcached wins
    Photo by Fikret tozak on Unsplash

    Most WordPress performance guides tell you to “enable object caching” without explaining which engine to use or what you’re actually optimizing for. Redis and memcached both cache database query results in memory, but they handle data persistence, eviction policies, and scale differently—and picking the wrong one can waste server resources or create new bottlenecks.

    Here’s how object caching actually works in WordPress, when each engine makes sense, and one non-obvious configuration detail that changes performance more than the engine choice itself.

    What object caching does in WordPress

    WordPress makes dozens of database queries per page load: post metadata, user permissions, theme options, widget settings. Object caching stores the results of those queries in RAM so subsequent requests skip the database entirely.

    Without object caching, every page view hits MySQL. With it enabled, WordPress checks the cache first. If the data exists and hasn’t expired, the query never runs. This matters most on sites with high traffic, complex queries, or shared hosting where database connections are rate-limited.

    The cache doesn’t replace page caching (which stores rendered HTML) or CDN edge caching (which serves static assets). It sits between WordPress and the database, cutting query volume by 40–80% on typical sites.

    Redis vs. memcached: the actual differences

    Both engines store key-value pairs in memory. The differences show up in three areas:

    Data persistence. Redis can write cache data to disk periodically, so a server restart doesn’t lose everything. Memcached stores data only in RAM—reboot the server, lose the cache. For most WordPress sites, this doesn’t matter; cache rebuilds in minutes. But if you’re caching computationally expensive data (API responses, complex WooCommerce queries), Redis persistence reduces rebuild load.

    Data structures. Redis supports lists, sets, sorted sets, and hashes. Memcached handles strings only. WordPress core uses simple key-value storage, so this rarely matters unless a plugin (like some analytics or membership tools) needs complex queries. WooCommerce session handling, for example, works better with Redis because it stores cart data as hashes.

    Eviction policies. Memcached uses LRU (least recently used) eviction: when memory fills, it drops the oldest unused items. Redis offers multiple policies (LRU, LFU, random, TTL-based). For WordPress, LRU works fine in both. The policy matters less than setting the right memory limit.

    Performance-wise, memcached is marginally faster for pure key-value lookups—10–15% in benchmarks. Redis trades that speed for flexibility. On a typical WordPress site serving 50,000 monthly visitors, you won’t notice the difference.

    When to use each engine

    Use memcached if: You’re running a straightforward content site (blog, magazine, newsletter archive), your hosting provider offers it pre-configured, or you want the simplest possible setup. Managed WordPress hosts like BigScoots often provision memcached by default because it’s lightweight and requires minimal tuning.

    Use Redis if: You run WooCommerce, a membership site, or any plugin that benefits from persistent sessions; you need cache data to survive server restarts; or you’re already using Redis for something else (job queues, rate limiting) and want to consolidate.

    If your host offers both and you’re unsure, start with memcached. It’s easier to configure and harder to misconfigure.

    The non-obvious detail: connection method matters more than engine choice

    Most WordPress object caching plugins default to TCP socket connections (127.0.0.1:6379 for Redis, 127.0.0.1:11211 for memcached). Switching to Unix sockets cuts latency by 20–40% because the connection skips network stack overhead—even on localhost.

    To use Unix sockets, your cache engine and WordPress plugin both need reconfiguration. For Redis with the Redis Object Cache plugin, edit wp-config.php:

    define('WP_REDIS_SCHEME', 'unix');
    define('WP_REDIS_PATH', '/var/run/redis/redis.sock');

    For memcached with the Memcached Object Cache plugin:

    $memcached_servers = array(
      'unix:///var/run/memcached/memcached.sock'
    );

    Your hosting provider needs to enable socket support—most managed hosts do, but you may need to open a support ticket. The socket path varies by server (check /var/run/ or ask support).

    On a test site serving 5,000 daily visitors, switching from TCP to Unix sockets dropped average query time from 18ms to 11ms. That’s more impact than switching from memcached to Redis.

    How to tell if it’s working

    Enable query monitoring with the Query Monitor plugin. Before object caching, you’ll see 40–80 database queries per page load. After enabling and warming the cache (visit a few pages), that should drop to 15–30.

    If query count doesn’t drop, check three things: cache isn’t connected (plugin shows “Disconnected” in settings), cache memory is too small (check maxmemory setting—allocate at least 128 MB), or your theme/plugins bypass the object cache with direct SQL queries (rare, but some poorly-coded tools do this).

    Object caching won’t fix slow page rendering or large image files—it only cuts database load. Pair it with page caching (WP Rocket, LiteSpeed) and a CDN for full effect.

    Running a high-traffic WordPress site? Subscribe to One Two Three Send for weekly deep-dives on hosting, performance, and infrastructure decisions that actually move the needle.

  • Productivity app webhooks time out after 30 seconds—here’s the fix

    Productivity app webhooks time out after 30 seconds—here’s the fix

    Productivity app webhooks time out after 30 seconds—here's the fix
    Photo by Brett Jordan on Unsplash

    If you’ve built any automation workflow that sends data between tools—Zapier to Airtable, Make to WordPress, a payment processor to your CRM—you’ve probably hit a webhook timeout without realising it.

    The symptom: a task starts, the spinner hangs, and eventually you get a vague “request failed” error. The cause is almost always the same: your receiving endpoint took longer than 30 seconds to respond, and the sender gave up.

    This isn’t a bug. It’s how most webhook systems are designed. And once you understand the constraint, you can route around it.

    Why 30 seconds is the standard cutoff

    Webhook senders—Zapier, Make, Stripe, ConvertKit, Memberful—don’t wait indefinitely for a response. They set a timeout, usually between 10 and 30 seconds, because:

    • They’re firing hundreds of thousands of webhooks per minute across all users
    • Open connections consume server resources
    • If your endpoint is slow or broken, they don’t want to block their entire queue

    Most platforms default to 30 seconds. Zapier and Make both cut off at that mark. Stripe allows 30 seconds for most events. Postmark’s inbound webhooks time out after 30 seconds. If your server hasn’t returned an HTTP 200 by then, the sender logs it as a failure and moves on.

    Some platforms retry. Stripe retries failed webhooks for up to three days with exponential backoff. Zapier retries once, then marks the task as errored. Make retries based on your scenario settings. But the initial timeout is non-negotiable.

    What actually takes longer than 30 seconds

    Most webhook receivers respond in under a second. But a few operations consistently blow past the limit:

    • Database writes that trigger cascading updates or recalculations
    • Image processing or file uploads chained inside the webhook handler
    • API calls to third-party services that are themselves slow (e.g., rendering a PDF, geocoding an address)
    • WordPress actions that run on save_post and process hundreds of post meta fields

    The worst offender: nesting multiple external API calls inside a single webhook receiver. Each call adds latency, and they stack. If you’re calling Clearbit for enrichment, then OpenAI for classification, then Airtable to log the result—all synchronously—you’ll hit 30 seconds easily.

    The fix: acknowledge fast, process async

    The pattern that works: your webhook endpoint should return HTTP 200 within a second or two, then hand off the real work to a background job.

    Here’s the flow:

    1. Webhook arrives at your server
    2. Validate the payload and signature (takes milliseconds)
    3. Write the raw payload to a queue, database row, or Redis key
    4. Return 200 OK immediately
    5. A separate worker process picks up the queued job and does the slow work

    This decouples acknowledgment from execution. The sender sees success. Your app processes the work without time pressure. If the background job fails, you handle retries internally instead of relying on the sender’s retry logic.

    In WordPress, that might mean using wp_schedule_single_event() to defer processing. In a Node app, it could be a Redis-backed Bull queue. In Python, Celery. The tool doesn’t matter—the principle does.

    When you can’t control the receiver

    Sometimes you’re triggering a webhook to a third-party service you don’t control—say, sending Zapier data that then hits another app’s API.

    If that downstream app is slow, Zapier times out. You can’t fix their code. But you can add a buffer step:

    • Send the webhook to a lightweight middleman endpoint you do control (a Cloudflare Worker, a simple Express server, a Make scenario that just writes to Airtable)
    • That endpoint acknowledges instantly and queues the payload
    • A separate process polls the queue and retries the slow destination with your own timeout and backoff logic

    It’s extra infrastructure, but it keeps your automation chain from breaking every time a third-party API has a slow day.

    Webhook timeouts aren’t going away. Thirty seconds is the ceiling. If your workflow assumes more time than that, it’ll fail intermittently—and intermittent failures are the hardest to debug. Acknowledge fast, process later, and your automations stay reliable even when the work is slow.

    Want more workflow architecture breakdowns like this? Subscribe to One Two Three Send—we dig into the mechanics that most operator blogs skip.