Running the System: Time, Self-Hosting, and Learning
DeskcommCRM’s continuity depends on more than the code that answers a message. It depends on several clocks, a distributed artifact that actually runs those clocks, and feedback that changes future behavior without silently changing the customer experience. This chapter connects follow-up timing, WhatsApp pacing, worker recovery, self-host packaging, observability, and the human-gated flywheel. The reader should leave able to tell when delay is a safety decision, what a self-host operator must keep healthy, and how the product can learn from failure without pretending that a proposal is already an improvement.
A conversational sales operation is full of delayed consequences. A customer may need a reply now, a follow-up tomorrow, a retry after an upstream outage, or a human decision after an automated sequence is exhausted. Treating all of these as “latency” hides their different owners and risks. DeskcommCRM’s design works better when each delay is understood as a clock with a purpose, a state, and an exit.
Not every clock should run at the same speed
The follow-up clock answers when the system should evaluate a demand again. A follow-up enrollment is attached to a contact and a pinned flow version, and its next_eval_at determines when the next node can be considered. The enrollment records whether it is active, waiting for a reply, paused by handoff, completed, canceled, or dead. An inbound message can wake a waiting flow; an opt-out can cancel it; a handoff can pause it. A flow that exhausts recovery without a response becomes visible to the operation instead of quietly disappearing at the end of its timer.
This clock is different from event-driven automation. An automation rule starts because something happened: a lead changed stage, a tag was added, a message arrived, or an external webhook was accepted. Follow-up starts because something has not happened for a configured period, or because an explicit future action is due. The distinction prevents the system from disguising absence as an event. Silence is not a message, but it can still be a meaningful state that needs a scheduled evaluation.
The channel clock has a different owner and a different risk. WhatsApp sending may need to be spaced to reduce the risk of damaging a number, especially when automated messages are involved. A number can also be in warm-up, at a daily cap, outside the permitted service window, or waiting for a session to become healthy. In those cases, the right action is not necessarily to ask the model for another sentence. The right action may be to delay the job, keep the demand visible, and send only when the channel’s conditions allow it.
The worker retry clock answers when a failed operation deserves another attempt. A timeout or temporary upstream failure may succeed later, so exponential backoff gives the dependency time to recover. A blocked contact or an invalid business state is different: repeating the call cannot make the decision valid. The queue therefore needs to distinguish a retryable incident from a terminal business veto. Otherwise the system either retries harmful work or generates a flood of dead-letter alerts that obscures the one action a human should take.
The session-health clock asks whether the transport itself is usable. A WhatsApp session can be starting, working, stopped, or failed. The watchdog and health paths maintain a durable view of that condition, while the send path can hold or re-drive queued work. A healthy web application does not prove that the WhatsApp session is connected, that the worker is draining its queue, or that the scheduler is firing.