Dev.to WebDev πŸ›  Dev πŸ‘ 1 πŸ“– 6 min read

Building conversation-first support on Cloudflare

We built DobroDesk around a simple observation: a support request does not become a different problem because it arrives by email, website chat or a mobile app. The customer still needs an answer. The team still needs co

We built DobroDesk around a simple observation: a support request does not become a different problem because it arrives by email, website chat or a mobile app. The customer still needs an answer. The team still needs context, ownership and a clear next step.

That led us to model the work as a conversation from the beginning. A message can start in one channel, pick up customer context and move to a teammate without becoming a second ticket record. The choice sounds like a product decision, but it reaches into storage, background work, public delivery and client releases.

Start with the data boundary

We use Cloudflare Workers as the application runtime. The first boundary is between information that describes the whole service and work that belongs to one customer workspace.

D1 holds the global catalog and account-level records such as authentication, workspace membership, billing pointers and routing metadata. A workspace's conversations, customers, messages and operational events live with that workspace in a Durable Object backed by SQLite. This keeps workspace state close to the consistency boundary that owns it.

Files have a different lifecycle from conversation state. R2 stores raw MIME, attachments, uploaded files, screenshots and export artifacts. Keeping those objects out of the transactional workspace database makes the data model easier to reason about and gives large files their own retention and delivery path.

This division also gives the operator a useful guarantee. When a teammate opens a conversation, the record, its customer context and the work associated with that workspace have one clear owner. Global routing and billing metadata do not become an accidental second copy of the conversation.

Make background work explicit

Support work rarely ends when the initial request returns. An email needs parsing. A conversation may need triage. A reply may need sending and retrying. A webhook may arrive after the browser has moved on.

Cloudflare Queues make those transitions explicit. DobroDesk uses queues for parsing, triage, sending, retries, webhook processing and spam review. The queue message represents work that can be retried and observed. The request that accepted the message does not have to pretend that every later operation has already succeeded.

Durable Objects complement that model. They keep the workspace-owned state and coordinate the changes that must be accepted in order. Together, the object and the queue let us distinguish a new request from a repeated delivery and a pending operation from a completed result.

That distinction matters in a support product. A duplicate provider event should not create a second conversation. A retry should not send the same reply twice. A stale browser action should not silently overwrite a newer conversation state. These are product behaviours expressed through infrastructure boundaries.

Let automation help without taking ownership away

AI is useful when it works inside a defined support process. It is risky when it receives an unrestricted copy of a workspace and is allowed to act without a clear owner.

DobroDesk uses approved knowledge, customer context and policy boundaries to decide what can inform a response. A standard AI reply can be prepared for approval. Sensitive, uncertain or high-impact cases stay with a person. The product can support automatic answers where a workspace has enabled that mode, while approval remains the right path for workflows that require review.

Configured actions follow the same rule. A booking flow can collect the fields a team needs, use the availability source that the workspace has connected and show a proposed result before it is confirmed. Only a successful configured operation adds its result to the conversation. If the request changes, a provider fails or the customer needs judgement, the flow hands the conversation to a teammate with the collected context.

This is why human handoff is part of the workflow rather than an error page. Automation can finish the routine path, but the customer should know how to reach a person when the routine path stops being safe or useful.

Give the public edge a different job

The public site has a separate responsibility from the workspace runtime. It needs to deliver localized pages and make those pages understandable to visitors and search engines.

The public pages are localized and prerendered. The edge resolves a public locale URL and serves the matching page. Static assets remain asset-first. Canonical URLs, hreflang links and locale sitemap entries come from the same locale configuration so a crawler does not have to interpret a browser cookie or wait for client-side JavaScript to discover the language version.

This separation keeps public delivery predictable. It also lets us improve the operator runtime without making public content depend on a workspace session.

Release clients as part of the system

A support client can outlive the deployment that first loaded it. The website widget therefore uses immutable versioned assets. The stable loader and the current and previous frame builds remain available for the active session window.

We extend public commands and payload fields before a backend starts requiring them. An older loader can continue an active session while a deployment rolls forward. A page reload should not discard a customer's draft, session pointer or conversation history just because the widget and backend were updated at slightly different times.

The same principle guides DobroDesk Mobile SDK 0.2.0. The published release contains artifact-only packages for iOS, Android, Capacitor, React Native and NativeScript. The Flutter package dobrodesk_sdk is available at version 0.2.0 on pub.dev. Checksums and installation metadata let an integration pin the exact artifacts it tested. Optional Android voice and push artifacts remain host decisions. The host application owns its microphone and notification permissions.

Versioning is a product boundary. It gives customers a stable integration contract while the service behind it continues to improve.

Measure a path without turning it into a promise

We test specific paths that matter to the product, including restored sessions, warm conversation switches, action results and runtime transitions. Those checks help us find duplicate reads, stale state and regressions in the flow a teammate actually uses.

A path measurement is evidence about that path. It is not a global service-level guarantee, a Core Web Vitals result or a promise that every browser and network will behave the same way. We keep those categories separate in internal verification and in public copy.

The same boundary applies to reliability claims. We can explain which transitions are versioned and which work is retryable. We should not turn that design into an uptime or scale number without a current production measurement that covers the claim.

The platform is the boundary between components

Cloudflare gives us the runtime primitives, but the useful result comes from how they meet. Workers handle the edge runtime. D1 keeps global account and routing records. Durable Objects own workspace state. R2 carries raw files and export artifacts. Queues make asynchronous work explicit. The widget and SDK keep the client contract versioned.

DobroDesk is the product built on those boundaries. A customer can ask for help, share context, complete a configured action or reach a person without being moved between unrelated data models. The team gets a conversation with ownership, history and a next step.

That is the engineering goal we keep returning to: make the normal support path simple, keep exceptions understandable and let every component own the work it is responsible for.

Explore DobroDesk or read the Mobile SDK documentation.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.