DEV Community

Cover image for Building a Multi-Account X Automation System: Slot Isolation by Design
HelperX
HelperX

Posted on • Originally published at helperx.app

Building a Multi-Account X Automation System: Slot Isolation by Design

When your SaaS manages multiple accounts for the same platform, the worst bug you can ship isn't a crash — it's cross-account bleed. One user's action affecting another user's account. One slot's misconfiguration leaking into another slot's behavior.

At HelperX, each X account lives in its own "slot." Here's how we designed slot isolation to make cross-slot bugs structurally impossible, not just unlikely.

What is a slot?

A slot is a single X account connected to HelperX. One user can have multiple slots. Each slot has:

  • Its own auth token (encrypted)
  • Its own proxy (separate IP)
  • Its own plan and daily caps
  • Its own module settings
  • Its own work-time window
  • Its own audit log
  • Its own daily counters

Slots don't know about each other. There's no shared state, no cross-references, no "account group" concept.

Why isolation matters for X automation

X's anti-abuse system watches for coordinated behavior. If two accounts:

  • Like the same tweet within minutes
  • Reply to the same thread with similar text
  • Follow the same batch of users

...X flags both accounts for coordinated amplification. This is one of the fastest paths to suspension.

If your system has any cross-slot state — shared queues, shared target lists, shared scheduling — you risk accidental coordination. Two slots independently finding the same trending tweet and both replying to it looks organic. Two slots drawing from a shared queue and replying to the same tweet looks like a bot network.

Isolation isn't just a clean architecture choice. It's a safety requirement.

The isolation model

Data isolation

Every database query is scoped to a slot ID. There is no query in the codebase that fetches data across slots without an explicit admin context.

// Every module operation is scoped
function getReplies(slotId) {
  return db.prepare(
    'SELECT * FROM replies WHERE slot_id = ?'
  ).all(slotId);
}

// Daily cap check — always per-slot
function canPerformAction(slotId, moduleType) {
  const today = getUTCDate();
  const count = db.prepare(
    'SELECT count FROM daily_counters WHERE slot_id = ? AND module = ? AND date = ?'
  ).get(slotId, moduleType, today);

  const plan = getSlotPlan(slotId);
  return (count?.count || 0) < plan.dailyCap;
}
Enter fullscreen mode Exit fullscreen mode

This isn't enforced by convention ("remember to add the slot_id filter"). It's enforced by the data access layer — every function that touches slot data takes slotId as a required parameter.

Network isolation

Each slot has its own proxy. This is required, not optional.

  • You can't start a module without a verified proxy
  • Two slots can't share the same proxy address
  • Proxy credentials are stored per-slot (encrypted)

Why separate proxies? X correlates activity by IP. Two accounts making automated requests from the same IP address is the simplest coordination signal to detect.

Counter isolation

Daily action counters are per-slot, per-module, per-day:

daily_counters:
  slot_id | module        | date       | count
  1       | reply_search  | 2026-06-03 | 47
  1       | top_repost    | 2026-06-03 | 3
  2       | reply_search  | 2026-06-03 | 89
Enter fullscreen mode Exit fullscreen mode

Slot 1 hitting its cap doesn't affect Slot 2. Slot 2 being on a higher plan doesn't bleed into Slot 1's limits.

Schedule isolation

Each module instance has its own:

  • Work-time window — Slot 1 can run 8 AM–8 PM, Slot 2 can run 12 PM–12 AM
  • Cycle interval — Slot 1 checks every 10 minutes, Slot 2 every 20
  • Delay settings — different randomized delay ranges per slot

This means two slots for the same user can simulate two different humans in two different timezones.

Server-side cap enforcement

Daily caps are enforced server-side, not client-side. The flow:

Module wants to perform action
  → Check daily_counters for this slot + module + today
  → Compare against plan limit for this slot
  → If under limit: perform action, increment counter
  → If at limit: skip, log "cap reached"
Enter fullscreen mode Exit fullscreen mode

The counter increment is atomic. Even if two module cycles overlap (shouldn't happen, but defense in depth), the counter can't drift past the plan limit.

Why server-side? A client-side cap can be bypassed by modifying the frontend or calling the API directly. Server-side means the cap is the cap — no overrides, no exceptions, no "just this once."

Audit log isolation

Every action a module takes is logged:

audit_log:
  slot_id | timestamp           | module       | action  | target_id      | status
  1       | 2026-06-03 14:23:11 | reply_search | reply   | 1798234567890  | success
  1       | 2026-06-03 14:25:44 | reply_search | like    | 1798234567890  | success
  2       | 2026-06-03 14:24:02 | top_repost   | retweet | 1798111222333  | success
Enter fullscreen mode Exit fullscreen mode

In the dashboard, you only see logs for the selected slot. There's no "all slots" view for module activity — by design. You manage each account independently because they are independent.

The plan-per-slot model

Most SaaS tools charge per user or per organization. We charge per slot because the isolation boundary is the slot, not the user.

One user can have:

  • Slot A on the Free plan (30 replies/day)
  • Slot B on Pro ($50/month, 300 replies/day)
  • Slot C on Standard ($20/month, 100 replies/day)

Each slot has different capabilities because each X account has different needs. A main brand account needs more features than a secondary presence account.

What isolation prevents

Real scenarios that slot isolation makes impossible:

Scenario 1: Coordinated liking
Without isolation, a shared "interesting tweets" queue could cause multiple accounts to like the same tweet. With isolation, each slot discovers tweets independently through its own keyword searches. The probability of two slots finding and acting on the same tweet is low and random — not systematic.

Scenario 2: Counter bleed
Without isolation, a bug in the counter logic could cause Slot A's replies to count against Slot B's cap (or worse, not count at all). With per-slot counters, a counter bug affects one slot.

Scenario 3: Proxy leak
Without isolation, a fallback mechanism could route Slot A's traffic through Slot B's proxy during a connection failure. With isolation, if Slot A's proxy fails, Slot A's module stops — it doesn't borrow another slot's connection.

Scenario 4: Config bleed
Without isolation, updating Slot A's keyword list could accidentally overwrite Slot B's. With slot-scoped data access, the update query physically can't touch another slot's data.

Trade-offs

Isolation has costs:

  • No cross-slot optimization — if two slots search for the same keyword, they do duplicate work. We accept this because the alternative (shared state) creates coordination risk.
  • No bulk management — you can't "apply this setting to all slots." Each slot is configured individually. This is slower for operators but safer for accounts.
  • Higher resource usage — each slot maintains its own state, timers, and counters. At thousands of slots, this adds up. So far, manageable.

The trade-off is always the same: convenience vs. safety. For X automation, safety wins.

Implementing isolation in your project

If you're building a multi-tenant system where tenants interact with the same external platform:

  1. Scope every query — tenant ID is a required parameter, not an optional filter
  2. No shared queues — if tenants draw from the same queue, their actions become correlated
  3. Separate external connections — different IPs, different sessions, different rate limit budgets
  4. Independent counters — one tenant's usage never affects another's limits
  5. Audit per tenant — cross-tenant audit views create information leakage
  6. Test with concurrent tenants — your integration tests should run multiple tenants simultaneously and verify no cross-contamination

The simplest test: run two slots targeting the same keyword. Verify they never act on the same tweet within the same cycle. If they do, your isolation has a leak.


HelperX manages multiple X accounts with full slot isolation — each account gets independent settings, proxy, caps, and audit logs. No cross-slot bleed by design.

Top comments (0)