
The request came in at the quarterly product review at a boiler manufacturer, a meeting already running long. The product manager for the commercial line puts up a slide: the residential connected boiler launched last year, customers like the app, and installers are asking for the same remote diagnostics on the commercial units. Can the cloud team have a second connected product line ready by next heating season?
The head of the 12-person cloud team does the math on a notepad. The residential backend has its own device registry, its own MQTT bridge, its own retry logic for the alerting service, its own secrets wiring, and a warranty registration flow that two engineers spent most of last spring stabilizing. None of it was designed to be shared. Supporting a second product line means building almost all of it again, with the same 12 people who are still fixing bugs in the first one.
If you lead software at a manufacturer of appliances, HVAC, water systems, building controls, or tools, this moment is probably familiar.
Why hardware-first companies end up rebuilding the backend
Manufacturers usually enter the cloud business one product at a time. A business unit funds a connected flagship, a small team builds what it needs, and the deadline shapes every decision. The result is a backend that works but is tightly coupled to one product, one cloud provider, and one set of infrastructure choices.
The deeper issue is where the engineering time goes. A connected product needs device connectivity, a user app, partner and ERP integrations, alerts, and long-running processes like onboarding and warranty claims. Very little of that work is about boilers. Most of it is plumbing:
- Choosing and operating a message broker, then writing retry and dead-letter handling around it
- Wiring up service discovery and secure service-to-service calls
- Managing secrets and credentials per environment
- Writing state persistence code against one specific database
- Building ad hoc state machines for processes that last days or weeks
Software companies have platform teams that solve these problems once. A manufacturer with a few dozen software engineers usually does not, and hiring experienced distributed-systems engineers is hard. So the same small team re-solves infrastructure for each product line, and the features customers notice get whatever time is left.
Why the usual workarounds fall short
Teams under pressure tend to reach for one of three shortcuts.
Copy the first backend. Forking feels fast. Within a year, you have two diverging codebases, and every security patch has to be applied twice.
Go all-in on one cloud’s managed services. This reduces operational work, but application code fills up with provider-specific SDK calls. That hurts when a large customer, a regional regulation, or an acquisition pushes you toward a different cloud.
Buy an end-to-end IoT platform. These often fit device connectivity well but help less with the business logic around the device, such as warranty flows and installer portals. Teams end up running a vendor platform and a custom backend side by side.
Each of these buys short-term speed by giving up either reuse or portability. A small team needs both.
The general approach: a platform of reusable building blocks
The pattern that works is borrowed from larger software organizations, scaled down: build a thin internal platform once and have every product line consume it. Four principles matter.
Separate application code from infrastructure choices. Product code should say “publish this event” or “save this state,” not “call the Kafka producer with these settings.” The infrastructure behind those calls should be configuration, swappable per environment or per cloud.
Standardize cross-cutting concerns in one place. Retries, timeouts, encryption between services, service identity, tracing, and metrics should come from the platform, not from each team’s custom code.
Make long-running processes durable by default. Onboarding, warranty claims, and firmware rollouts can last weeks and must survive restarts without hand-built recovery logic.
Package it as a template. A new product line should start from a repository template with the platform already wired in.
None of this requires a specific tool. But writing and maintaining that abstraction layer yourself is exactly the kind of plumbing a small team cannot afford, which is where an existing runtime helps.
Implementing it with Dapr
Dapr (Distributed Application Runtime) is an open-source CNCF graduated project that provides these building blocks as APIs. It runs as a sidecar next to each service, on Kubernetes, on VMs, or self-hosted, and your code talks to it over HTTP or gRPC. The relevant building blocks map closely to what a connected-product backend needs:
- Pub/sub for device events and alerts, with pluggable brokers such as Kafka, RabbitMQ, Redis, or cloud messaging services. Messages use CloudEvents, delivery is at-least-once, and dead-letter topics are supported.
- State management with pluggable stores such as PostgreSQL, Redis, Cosmos DB, DynamoDB, or MongoDB, including optimistic concurrency through ETags and a transactional outbox.
- Service invocation between services by app ID, with service discovery and mTLS between sidecars by default.
- Bindings for connecting to external systems such as partner APIs and enterprise systems.
- Secrets for reading credentials from a secret store without hard-coding a provider.
- Workflows for durable, long-running processes written as code.
Because brokers and stores are configured as components, the same code can run on different clouds. Resiliency is declared in YAML policies (timeouts, retries with constant or exponential backoff, circuit breakers) rather than written into each service. Every sidecar exposes Prometheus metrics, and OpenTelemetry tracing propagates across service calls and pub/sub, so your operations view looks the same for every product line.
There is precedent for this. A water-technology manufacturer’s ~40-person team built two cloud-native connected-device products on Dapr in two years. That is the outcome the boiler team in the opening scene needs: a second product without a second platform.
Durable workflows for the long processes
The processes that hurt most are the slow ones. A warranty claim might wait days for an installer’s photos and a manager’s approval. Dapr Workflow handles these as code, with event-sourced history stored in a state store. If a process crashes, the workflow replays from its history and completed activities are not re-executed.
A simplified warranty claim in the Python SDK might look like this:
import dapr.ext.workflow as wf
from datetime import timedelta
wfr = wf.WorkflowRuntime()
retry = wf.RetryPolicy(first_retry_interval=timedelta(seconds=2), max_number_of_attempts=5, backoff_coefficient=2, max_retry_interval=timedelta(minutes=1))
@wfr.workflow(name=”warranty_claim”)
def warranty_claim(ctx: wf.DaprWorkflowContext, data: dict):
r = yield ctx.call_activity(validate_serial, input=data, retry_policy=retry)
if not r.get(“valid”):
return {“status”: “rejected”}
evt = ctx.wait_for_external_event(“approval”)
timer = ctx.create_timer(timedelta(hours=48))
winner = yield wf.when_any([evt, timer])
if winner == timer:
yield ctx.call_activity(escalate_claim, input=data)
else:
payload = evt.get_result()
yield ctx.call_activity(issue_replacement, input=payload)
Orchestrator code must be deterministic, so I/O belongs in activities. SDKs also exist for .NET, Java, Go, and JavaScript, which matters if your team writes mostly C# or Java. Every product line can then reuse the same claim pattern, swapping only product-specific activities.
Running the platform with a small team
Adopting Dapr shifts some work to operating the runtime itself: control-plane upgrades, certificate rotation, and keeping configuration consistent across clusters. A small team should plan for that honestly. A managed environment is one way to shrink it: Azure Container Apps, for example, offers Dapr as a built-in managed integration. Teams that stay on their own Kubernetes clusters can look at the free Dapr Ops Dashboard, which handles automated upgrades, certificate rotation, and best-practice checks; its maker, Diagrid, was founded by the creators of Dapr and also sells commercial support. Run a trial against the real operational load of your own clusters before signing anything.
A practical roadmap for your team
- Inventory the plumbing. List every infrastructure concern in your current backend and mark which ones the next product line would need again.
- Pick one service to move first. An event-driven alerting service is often a good candidate. Move its broker and state access behind Dapr APIs.
- Write the component and resiliency configuration once. Keep pub/sub, state, secrets, and resiliency definitions in a central repository.
- Move one long-running process to a workflow. Pick the one that causes the most support tickets when it fails halfway.
- Build the product-line template. Package the service skeleton, components, policies, CI pipeline, and dashboards into a repository template.
- Launch the second product line from the template. Measure how much you reused versus rebuilt.
- Decide on operations support. Choose whether to run the runtime yourselves, use a managed cloud integration, or bring in a provider for a managed or supported setup.
Before you call the platform ready, check these items:
- ☐ No product service imports a broker or database SDK directly
- ☐ Credentials come from a secret store, not environment files
- ☐ Retries and timeouts are defined in shared policies
- ☐ Every long-running process survives a restart in a test environment
- ☐ Traces and metrics look the same for every product line
- ☐ A new engineer can deploy a new service from the template in a day
Conclusion
The boiler manufacturer’s cloud team does not need to double in size to support a second product line. It needs to stop treating each product as a fresh backend project. When pub/sub, state, service calls, secrets, and long-running processes come from shared building blocks, the team’s time moves from plumbing to the features customers actually see.
Open-source runtimes like Dapr give small teams the same kind of portable foundation that large software companies build internally, and durable workflows remove a whole category of hand-built recovery code. If you want help running it, a durable workflow platform or a commercial support option is one route to evaluate alongside managed cloud offerings. Start with one service, prove the reuse, and let the second product line be the test.