Chrome Browser Multi-Instance Isolation (Part 3): State Sync, Locking, and Migration

Three synchronization strategies for multi-agent scenarios: optimistic locking, pessimistic locking, shared nothing. Plus session migration between browser instances.

16Yun Engineering TeamApr 12, 20262 min read

The Core Contradiction in Multi-Agent State Management

In single-agent scenarios, state management is simple: one agent operates one page, state lives on that page. Success → continue. Failure → retry.

In multi-agent scenarios, complexity multiplies:

  1. Shared state: Two agents operating the same target site — who updated the order? Who modified the config?
  2. Inconsistent views: Agent A recorded "form submitted" while Agent B queries and sees "not submitted."
  3. Session mobility: Agent A's session needs to move to another node, but cookies and localStorage are bound to the original Chrome Profile.

Problem 1: Shared State Synchronization

Three Strategies

Optimistic Locking

Assumes conflicts are rare. Record version on read, check version on write:

def update_inventory(store_id, new_count, expected_version):
    result = db.execute(
        "UPDATE inventory SET count = ?, version = version + 1 \
         WHERE store_id = ? AND version = ?",
        [new_count, store_id, expected_version]
    )
    if result.affected_rows == 0:
        raise ConflictError("Updated by another agent")

Best for read-heavy, write-light workloads.

Pessimistic Locking

Lock the resource before operating:

def lock_and_update(store_id):
    lock_key = f"lock:inventory:{store_id}"
    acquired = redis.setnx(lock_key, "locked", expire=30)
    if not acquired:
        raise ResourceBusyError(f"Store {store_id} locked by another agent")
    try:
        update_inventory(store_id)
    finally:
        redis.delete(lock_key)

Best for write-heavy workloads.

Shared Nothing

Each agent operates only on assigned resources:

AGENT_A_STORES = ["store_1", "store_2"]
AGENT_B_STORES = ["store_3", "store_4"]

No sync needed — no shared state. Simplest in theory, most overlooked in practice.

Problem 2: Session Migration

Scenario

Agent A logged into a target site on Browser Instance A, accumulated 20 minutes of state — cookies, localStorage, IndexedDB. Instance A needs to restart (memory leak, version update, node failure). Session must move to Instance B without losing login state.

Approach 1: Export/Import Storage State

Problem: HttpOnly cookies can't be read via JavaScript. Must use CDP's Network.getCookies.

Approach 2: CDP Network API

# Export
cookie_result = cdp.send("Network.getCookies")
state["cookies"] = cookie_result["cookies"]
 
# Import to new session
cdp.send("Network.setCookies", {"cookies": state["cookies"]})

Captures HttpOnly cookies but requires CDP-level access.

Approach 3: Reuse Persistent Profile

Most reliable: copy the entire Chrome Profile directory:

# Source machine
tar czf profile_backup.tar.gz -C /data/profiles/agent_a .
 
# Target machine
tar xzf profile_backup.tar.gz -C /data/profiles/agent_a/

More practical: copy only the Storage subdirectory:

tar czf session_state.tar.gz \
  -C /data/profiles/agent_a/Default \
  Cookies Cookies-journal Local\ Storage IndexedDB

Problem 3: Operation Orchestration

When Agent A and B both issue different operations on the same page simultaneously, page state becomes unpredictable.

Strategy: Serialize via Central Queue

class OperationQueue:
    async def enqueue(self, target_key, operation):
        await self.redis.rpush(f"op_queue:{target_key}", operation)
 
    async def dequeue(self, target_key):
        return await self.redis.blpop(f"op_queue:{target_key}", timeout=5)
 
queue = OperationQueue(redis)
await queue.enqueue("store_1", {"action": "update_price", "value": 99.99})
await queue.enqueue("store_1", {"action": "update_stock", "value": 50})
while op := await queue.dequeue("store_1"):
    execute_operation(op)

Summary

Multi-agent state management is at least an order of magnitude more complex than single-agent:

  1. Shared state sync — optimistic locking, pessimistic locking, or shared nothing
  2. Session migration — CDP Cookie export/import or Profile directory copy
  3. Operation orchestration — serialized queues for ordering

One principle to remember: two agents should never operate the same page in the same browser simultaneously. Either isolate resources (shared nothing) or serialize operations (queue). Don't let two brains control the same hands.

Need an enterprise proxy plan?

We can tailor architecture to your target domains, concurrency, and reliability goals.