Skip to content
Search

ROS2:Basic:CloudflareArchitecture

lastmod 2026-03-26created 2026-03-262 edits

Analysis of whether Cloudflare Workers / Durable Objects can replace ROS2 communication

An analysis of whether Cloudflare Workers or Durable Objects can take over the server role for topics/services in ROS2 through plain HTTP requests.

ROS2 communication model vs Cloudflare runtime

ROS2 communication characteristics

Pattern

Characteristics

Frequency

Examples

Topic (Pub/Sub)

One-way stream, high frequency

10~1000Hz

/joint_states, /camera/image

Service (Req/Res)

Synchronous request/response

Irregular

/robot/enable, /get_state

Action (Long-running)

Asynchronous, feedback stream

Seconds to minutes

MoveToPoint, FollowTrajectory

Cloudflare runtime characteristics

Runtime

State

Connection

CPU limit

Suitable use

Workers

Stateless

HTTP only

30s (free) / 15min (paid)

One-off API requests

Durable Objects

Stateful

HTTP + WebSocket

No limit (hibernation when idle)

Real-time sessions, state management

Replaceability by pattern

1. ROS2 Service → Workers (replaceable)

A ROS2 Service is essentially Request/Response, so it is the same pattern as an HTTP API.

[Web UI] → POST /api/agents/:id/commands → [Worker] → [Edge Agent] → [ROS2 Service Call]
                                                        ← 결과 반환 ←

Workers are enough. However, Workers do not call ROS2 directly; the Edge Agent relays.

2. ROS2 Topic (high frequency) → Durable Objects (conditionally possible)

[ROS2 Topic 100Hz] → [Edge Agent에서 다운샘플링 1~10Hz]
                      → WebSocket → [Durable Object] → WebSocket → [Web UI]

Why it is possible:

  • Durable Objects support WebSocket and keep state
  • The WebSocket Hibernation API can cut costs while idle

Constraints:

  • The Edge Agent must downsample (sending 100Hz as is makes costs explode)
  • Communication between Durable Objects is inefficient — map 1 Agent = 1 Durable Object
  • Unsuitable for binary data (camera images) — bandwidth/cost issues

3. ROS2 Action (long-running tasks) → Durable Objects (suitable)

[Web UI] → "Move to Point A" → [DO] → [Edge Agent] → [ROS2 Action]
[Web UI] ← 피드백 스트림 ←      [DO] ← progress 30% ← [Edge Agent]
[Web UI] ← 피드백 스트림 ←      [DO] ← progress 70% ← [Edge Agent]
[Web UI] ← 완료 ←              [DO] ← done ←          [Edge Agent]

The pattern where Durable Objects shine the most. State persistence + bidirectional WebSocket communication.

                    Cloudflare Edge
                    ┌─────────────────────────────────┐
                    │                                 │
[Web UI] ──HTTP──→  │  Worker (Hono)                  │  ← 명령, CRUD, 인증
                    │    │                            │
                    │    ├── Agent DO ────WebSocket──→ │ ──→ [Edge Agent]
                    │    │   (per agent)              │
                    │    │   - 연결 상태 관리          │
                    │    │   - 텔레메트리 릴레이       │
                    │    │   - 명령 큐잉/추적          │
                    │    │                            │
[Web UI] ←─WSS───  │    └── 브라우저에 WebSocket 제공 │
                    │                                 │
                    └─────────────────────────────────┘

Core design: Durable Object code example

// Durable Object: Agent 1개당 1개 인스턴스
export class AgentSession extends DurableObject {
  // Edge Agent WebSocket (1개)
  private agentSocket: WebSocket | null = null;
  // 브라우저 WebSocket (N개 - 대시보드 보는 사용자들)
  private viewers: Set<WebSocket> = new Set();

  async fetch(request: Request) {
    const url = new URL(request.url);

    if (url.pathname === '/connect-agent') {
      // Edge Agent가 연결
      const [client, server] = Object.values(new WebSocketPair());
      this.agentSocket = server;
      server.accept();
      server.addEventListener('message', (e) => {
        // 텔레메트리를 모든 viewer에 브로드캐스트
        for (const viewer of this.viewers) {
          viewer.send(e.data);
        }
        // 필요시 storage에 저장
      });
      return new Response(null, { status: 101, webSocket: client });
    }

    if (url.pathname === '/connect-viewer') {
      // 브라우저 대시보드가 연결
      const [client, server] = Object.values(new WebSocketPair());
      this.viewers.add(server);
      server.accept();
      server.addEventListener('message', (e) => {
        // 브라우저→Agent 명령 전달
        this.agentSocket?.send(e.data);
      });
      server.addEventListener('close', () => this.viewers.delete(server));
      return new Response(null, { status: 101, webSocket: client });
    }

    // REST: 명령 전송, 상태 조회 등
    if (url.pathname === '/command') {
      const cmd = await request.json();
      this.agentSocket?.send(JSON.stringify(cmd));
      // 명령 추적을 위해 storage에 저장
      await this.ctx.storage.put(`cmd:${cmd.id}`, cmd);
      return Response.json({ status: 'sent' });
    }
  }
}

Areas that cannot be replaced (Edge Agent required)

Function

Reason

Direct ROS2 DDS communication

DDS is UDP multicast — not possible over HTTP/WebSocket

Real-time control loop

Needs <10ms latency — a cloud round trip is not possible

E-Stop safety function

Must work even when the network is disconnected

Camera frame processing

Bandwidth/latency — process at the Edge and send only the results

Downsampling/filtering

Reduce high-frequency topics to a level that can be sent to the cloud

Conclusion

Role

Workers

Durable Objects

Edge Agent

Agent CRUD, authentication

O

-

-

Command delivery (replaces Service)

O

O (queuing)

Relay

Telemetry relay (replaces Topic)

X

O (WebSocket)

Downsampling required

Action tracking (feedback)

X

O

Relay

Direct ROS2 DDS communication

X

X

Required

Safety function (E-Stop)

X

X

Required

Workers + Durable Objects can fully replace the "cloud-side server", but the Edge Agent is still required for the ROS2 bridge + safety functions + data preprocessing. Having Durable Objects act as a per-Agent real-time session hub is the most natural design.

See also

author Zer0 sitemap