duplicati/ngclient: The Zoneless Angular Rebirth of a Backup Giant

How a legacy C# engine adopted Signals, automated SDKs, and a modern web architecture to outshine CLI-only competitors.

7 min read • View on GitHub • More from duplicati

A wide shot of a heavy iron bank vault door with a sleek modern glass touchpad embedded in the center, illustrating the contrast between legacy backend and modern frontend.
The new Duplicati client wraps a decade-old C# backup engine in a cutting-edge Angular 21 interface.
Key Takeaways

The UI Moat

In the world of open-source backups, the command line is king. Tools like Restic, Borgmatic, and Duplicacy dominate discussions among sysadmins and DevOps engineers, praised for their speed, content-defined chunking, and scriptability. Yet, Duplicati has maintained a massive user base for nearly a decade. Its secret weapon? A native, comprehensive web interface.

For users who prefer a graphical wizard to YAML files or command-line flags, Duplicati has always been the default choice. It offers point-and-click configuration, built-in scheduling, and native support for over 20 cloud storage providers without requiring external tools like rclone. But a UI built years ago eventually shows its age.

Duplicati wins if you need a web UI or native cloud storage support (S3, B2, Google Drive) without extra tooling.

Self-Hosting SH, Tech Reviewer · DEV Community Review

To protect its most valuable asset—accessibility—the Duplicati team initiated a complete rewrite. The duplicati/ngclient repository is not an iterative update; it is a radical leap forward. It abandons the old frontend architecture in favor of a cutting-edge Angular 21 application, leveraging the latest features of the framework to build a responsive, SaaS-like experience over a heavy local file-system engine.

Escaping the Zone

The most impressive technical feat of the new client is its adoption of "zoneless" Angular. Historically, Angular applications relied on a library called Zone.js to track asynchronous operations and trigger change detection across the entire component tree. This works well for typical web apps, but it becomes a massive performance bottleneck when dealing with high-frequency updates.

A backup tool like Duplicati processes thousands of file updates per second. If the UI attempted to track the progress bar using Zone.js, the constant change detection cycles would grind the browser to a halt. The ngclient solves this by using provideZonelessChangeDetection() and relying entirely on Angular Signals.

Signals allow the client to update specific UI components (like a progress bar) instantly without triggering global change detection cycles.

Signals provide a reactive primitive that tells the framework exactly which piece of state changed and which component needs to re-render. By managing the StatusBarState and SysinfoState with Signals, the client can process rapid telemetry from the C# backend with zero UI stutter.

The Auto-Generated Bridge

Connecting a brand-new TypeScript UI to a sprawling, ten-year-old C# backend presents a massive synchronization challenge. The Duplicati backend exposes hundreds of endpoints and complex Data Transfer Objects (DTOs) for configuring backup sources, schedules, and cloud destinations.

A close-up of a complex mechanical loom pulling raw, jagged metal punch cards from a hopper and weaving them into a perfectly ordered, pristine paper blueprint.
The OpenAPI generation pipeline acts as a translator, turning raw C# endpoints into structured, type-safe TypeScript interfaces.

Instead of manually writing TypeScript interfaces and HTTP services, the team implemented an automated pipeline using @hey-api/openapi-ts. By pointing the generator at the backend's Swagger JSON definition, they produce a massive, type-safe SDK on every build.

// openapi-ts.config.ts configuration
import { defineConfig } from '@hey-api/openapi-ts';

export default defineConfig({
  client: 'legacy/angular',
  input: 'http://localhost:8200/swagger/v1/swagger.json',
  output: 'projects/ngclient/src/app/core/openapi',
});

This ensures that if a C# developer adds a new field to a BackupDto, the frontend build will immediately fail if it isn't updated to handle it. It is a textbook example of using modern tooling to safely bridge the gap between legacy core logic and modern presentation.

The Interface Divide

The introduction of the ngclient solidifies Duplicati's position in the backup ecosystem. While other tools focus on optimizing chunking algorithms for the terminal, Duplicati is doubling down on the belief that data protection should be accessible to everyone, not just those comfortable writing bash scripts.

FeatureDuplicati (ngclient)BorgmaticRestic
Configuration ParadigmVisual UI WizardDeclarative YAMLCLI Flags / Scripts
State FeedbackReal-time WebSocket UITerminal StdoutTerminal Stdout
Target AudienceProsumers / SMBsSysadminsDevOps / Engineers

By adopting Angular 21, Signals, and an automated OpenAPI pipeline, the duplicati/ngclient project demonstrates how to effectively modernize a legacy application. It proves that you don't have to rewrite a decade of stable core logic to deliver a modern, high-performance user experience.