Repository: aerospike/aerospike-backup-service
Pull request #356: APPS-1653 Update documentation and DTO fields description
Author: login: korotkov-aerospike
Created: 2025-05-12T11:11:20Z | Merged: 2025-05-15T13:48:47Z



Diff:
diff --git a/README.md b/README.md
index f8dbea880..041bfa886 100644
--- a/README.md
+++ b/README.md
@@ -12,36 +12,198 @@ Use the [OpenAPI generation script](./scripts/generate-openapi.sh) to generate a
 A pre-built OpenAPI specification is available in Swagger
 format [here](https://aerospike.github.io/aerospike-backup-service/).
 
-## Table of contents
-
-- [Getting Started](#getting-started)
-- [User Guide](#user-guide)
-- [Build From Source](#build-from-source)
-- [Usage](#usage)
-- [Monitoring](#monitoring)
+# Table of contents
+
+<!-- toc -->
+
+- [Getting started](#getting-started)
+- [User guide](#user-guide)
+  * [Run](#run)
+  * [Configuration](#configuration)
+    + [Configuration File Format](#configuration-file-format)
+    + [Configuration with API](#configuration-with-api)
+  * [Monitoring](#monitoring)
+  * [Example requests and responses](#example-requests-and-responses)
+    + [Backup](#backup)
+    + [Restore](#restore)
 - [FAQ](#faq)
-
-## Getting started
+  * [What happens when a backup doesn’t finish before another starts (for the same routine)?](#what-happens-when-a-backup-doesnt-finish-before-another-starts-for-the-same-routine)
+  * [Can multiple backup routines be performed simultaneously?](#can-multiple-backup-routines-be-performed-simultaneously)
+  * [Which storage providers are supported?](#which-storage-providers-are-supported)
+- [Build from source](#build-from-source)
+    + [Prerequisites](#prerequisites)
+    + [Build the service](#build-the-service)
+    + [Build Docker image](#build-docker-image)
+    + [Build Linux packages](#build-linux-packages)
+    + [Release](#release)
+- [Migration Guide](#migration-guide)
+  * [v3 -> v3.1](#v3---v31)
+  * [v2 -> v3](#v2---v3)
+
+<!-- tocstop -->
+
+# Getting started
 
 Aerospike Backup Service reads configurations from a YAML file provided when the service is launched. See [Run](#run)
 for specific syntax.
-A sample configuration file and docker-compose script will help you get started testing the service.
-Follow the [docker-compose instructions](./docker-compose) to set up your test environment.
 
 Linux installation packages are available
 under [releases](https://github.com/aerospike/aerospike-backup-service/releases).
 
-## User guide
+# User guide
 
-### Entities
+This section covers basic usage scenarios for the Aerospike Backup Service.
 
-Each entity defined in the API specification has endpoints for reading and writing backup configurations at general or
-granular levels.
+## Run
 
-For specifics and example values, see the [OpenAPI docs](https://aerospike.github.io/aerospike-backup-service/).
+#### Binary
+
+Run as a binary using a configuration file:
+
+```console
+./aerospike-backup-service -c config.yml
+```
+
+Help:
+
+```console
+./aerospike-backup-service -h
+Aerospike Backup Service
+
+Usage:
+  aerospike-backup-service [flags]
+
+Flags:
+  -c, --config string   configuration file path/URL
+  -h, --help            help for aerospike-backup-service
+  -r, --remote          use remote config file
+  -v, --version         version for aerospike-backup-service
+```
+
+Set the configuration file path with `-c`.
+
+Without the `-r` flag, the file specified after `-c` is the actual configuration file.
+With the `-r` flag, the file specified after `-c` contains the path or URL to the actual configuration file.
+
+For example, you may store your configurations remotely, such as on AWS S3 storage.
+In this case, you could have a `remote_config.yaml` file containing S3 details:
+<!-- RemoteConfig -->
+
+```yaml
+s3-storage:
+  bucket: as-backup-bucket
+  path: config.yml
+  s3-region: eu-central-1
+```
+
+Run the server
+
+```bash
+./aerospike-backup-service -c remote_config.yaml -r
+```
+
+#### Docker
+
+Run in a container with a custom configuration file:
+
+```bash
+docker run -d -p 8080:8080 -v config.yml:/app/config.yml --name backup-service backup-service
+```
+
+#### Service
+
+Run as service (default path for config is `/etc/aerospike-backup-service/aerospike-backup-service.yml`):
+
+```bash
+sudo systemctl start aerospike-backup-service
+```
+
+view service logs:
+
+```bash
+sudo journalctl -u aerospike-backup-service -n 100 --no-page -f
+```
+
+## Configuration
+
+### Configuration File Format
+
+The configuration system in the Aerospike Backup Service is designed around modular entities—clusters, storage, backup
+policies, secret agents and routines—that you define and then connect together.
+
+A backup routine is the central piece of configuration: it ties together all the other entities to define how and when
+backups occur. When defining a routine, you reference:
 
-#### Configuration
+* A cluster to specify the Aerospike cluster to back up.
+* A storage configuration that defines where the backups are stored.
+* A backup policy that controls backup behavior.
 
+Each of these referenced components must be created and named in the configuration before the routine can use them. This
+modular approach lets you reuse and combine policies, clusters, and storage setups across multiple routines.
+
+#### Configuration file example
+
+<!-- DefaultConfig -->
+
+```yaml
+# yaml-language-server: $schema=https://raw.githubusercontent.com/aerospike/aerospike-backup-service/refs/tags/v3.1.0/docs/config.schema.json
+---
+aerospike-clusters:
+  abs-cluster: # <--- Custom cluster name
+    seed-nodes:
+      - host-name: localhost
+        port: 3000
+    credentials:
+      user: tester
+      password: secret:asbackup:psw # Password will be fetched from the secret agent
+      secret-agent-name: secret-agent  # <--- Refers to the secret agent name under secret-agents
+
+secret-agents:
+  secret-agent: # <--- Custom secret agent name
+    address: localhost
+    port: 5000
+    connection-type: tcp
+
+storage:
+  s3: # <--- Custom storage name
+    s3-storage: # Storage type; can be one of "local-storage", "s3-storage", "azure-storage", "gcp-storage"
+      path: backups
+      bucket: as-backup-bucket
+      s3-region: eu-central-1
+      min-part-size: 50_000_000 # Upload chunk size in bytes (May affect performance)
+
+backup-policies:
+  dailyBackupPolicy: # <--- Custom policy name
+    parallel: 8 # Parallelism level (May affect performance)
+    file-limit: 1000 # Max backup file size in MB (May affect performance)
+    compression: # Backup files will be compressed before uploading (May affect performance)
+      mode: ZSTD
+      level: 1
+    retention:
+      full: 10 # Retain 10 full backups
+      incremental: 5 # Retain incremental backups for the 5 latest full backups
+
+backup-routines:
+  dailyLocalBackupRoutine: # <--- Custom routine name
+    interval-cron: "@daily" # Full backup will be triggered daily at midnight
+    incr-interval-cron: "0 */2 * * * *" # Incremental backups every 2 hours
+    source-cluster: abs-cluster         # <--- Refers to the cluster name under aerospike-clusters
+    storage: s3                         # <--- Refers to the storage name under storage
+    backup-policy: dailyBackupPolicy    # <--- Refers to the policy name under backup-policies
+```
+
+Several configuration fields in the YAML file are marked with `May affect performance`.
+These settings (such as parallel, file-limit, min-part-size, and compression)
+can have a significant impact on backup throughput.
+We recommend experimenting with different values in your environment to find the optimal balance.
+
+### Configuration with API
+
+Each entity defined in the API specification has endpoints for reading and writing backup configurations at general or
+granular levels. While the API provides full control over the configuration, for most use cases,
+it’s preferable to configure the service via the YAML configuration file, which is easier to maintain.
+
+For specifics and example values, see the [OpenAPI docs](https://aerospike.github.io/aerospike-backup-service/).
 The endpoints defined within the configuration section allow users to view or modify the configuration file.
 Endpoints ending with /config enable reading and modifying the entire file at once, while endpoints like
 `/config/clusters`, `/config/policies`, `/config/routines`, and `/config/storage` provide more granular control.
@@ -96,57 +258,6 @@ update an existing routine.
 :warning: Incremental backups are deleted if they are empty and after each full backup. System metadata is backed up
 only on full backups.
 
-### Operations
-
-- List backups: Returns the details of available backups. A time filter can be added to the request.
-- Restore from path: Starts a restore operation from a specified backup folder.
-- Restore from a timestamp: Given a routine name, searches for the closest full backup to the given timestamp and
-  applies the backup in the following order: full backup first, then incremental backups up to the given point in time,
-  if they exist.
-
-## Usage
-
-### Service help
-
-```
-% ./backup -h
-Aerospike Backup Service
-
-Usage:
-  Use the following properties for service configuration [flags]
-
-Flags:
-  -c, --config string   configuration file path/URL
-  -h, --help            help for Use
-  -r, --remote          use remote config file
-  -v, --version         version for Use
-```
-
-Set the configuration file path with `-c`.
-
-Without the `-r` flag, the file specified after `-c` is the actual configuration file.
-With the `-r` flag, the file specified after `-c` contains the path or URL to the actual configuration file.
-
-For example, you may store your configurations remotely, such as on AWS S3 storage.
-In this case, you could have a remote_config.yaml file containing S3 details, and you would run the server with
-`-c remote_config.yaml -r`.
-
-### Run
-
-Run as a binary using a configuration file:
-
-```bash
-./build/target/aerospike-backup-service -c config/config.yml
-```
-
-Run in a container with a custom configuration file:
-
-```bash
-docker run -d -p 8080:8080 -v custom_config.yml:/app/config.yml --name backup-service backup-service
-```
-
-Example configuration files can be found in the [config](./config/) folder.
-
 ## Monitoring
 
 The service exposes a wide variety of system metrics that [Prometheus](https://prometheus.io/) can scrape, including the
@@ -175,243 +286,95 @@ on liveness and readiness probes for more information.
 The HTTP metrics endpoint can be found on
 the [OpenAPI specification](https://aerospike.github.io/aerospike-backup-service/) page.
 
-## Build from source
-
-### Prerequisites
-
-- Go 1.22
-
-### Build the service
-
-The following command generates a binary under the `build/target` directory.
-
-```bash
-make build
-```
-
-### Build Docker image
-
-#### Multiplatform
-
-```bash
-DOCKER_USERNAME="<jforg-username>" DOCKER_PASSWORD="<jfrog-password>" TAG="<tag>" make docker-buildx 
-```
-
-#### For local use
-
-```bash
-TAG="<tag>" make docker-build
-```
-
-### Build Linux packages
-
-Run `make packages`.
-This will generate a `rpm/deb` package for supported platforms (`linux/amd64`,`linux/arm64`) with respective `sha256`
-checksum file in the `build/target` directory.
-See the quick [guide](build/package/README.md) on how to get started with the Linux packages.
-
-### Release
-
-Use the following commands before a release to update the version.
-
-```bash
-NEXT_VERSION="<version>"  make release
-NEXT_HELM_CHART_VERSION="<helm-chart-version>" make helm-chart-release
-git add --all
-git commit -m "Release: "$(cat VERSION)""
-git tag "$(cat VERSION)"
-git push 
-```
-
-## FAQ
-
-### What happens when a backup doesn’t finish before another starts (for the same routine)?
-
-- **Full Backups:**
-    - Full backups cannot overlap. If a scheduled full backup is due to start but the previous one is still running, the
-      new backup is skipped entirely. It is not queued but will wait for the next scheduled execution.
-    - Full backups always take priority over incremental backups. If an incremental backup is running when a full backup
-      is scheduled, the full backup will start as planned, and the incremental backup will continue running without
-      interruption.
-
-- **Incremental Backups:**
-    - Incremental backups are skipped if any other backup (full or incremental) is still running.
-    - Incremental backups will not run until at least one full backup has been successfully completed.
-
-### Can multiple backup routines be performed simultaneously?
-
-Yes, multiple backup routines can run in parallel. Furthermore, it is possible to back up different namespaces from the
-same cluster using separate routines with different schedules, all running simultaneously.
-
-To manage resource utilization, you can configure the `cluster.max-parallel-scans` property to limit the number of read
-threads operating on a single cluster.
-
-### Which storage providers are supported?
-
-The backup service supports the following storage providers:
-
-- **AWS S3** (or compatible services such as MinIO)
-- **Microsoft Azure**
-- **Google Cloud Storage**
-- **Local storage** (files stored on the same machine where the backup service is running)
-
 ## Example requests and responses
 
-### Read configurations
-
-This section details how to fetch configurations for clusters, policies, and storage options. This is useful for setting
-up or verifying the configuration of your system.
-
-#### Get cluster configuration
+The following sections provide example requests and responses for various operations.
+For full API documentation, refer to
+the [Aerospike Backup Service OpenAPI specification](https://aerospike.github.io/aerospike-backup-service/#/System/metrics).
 
-This endpoint returns the configurations of existing clusters, including the default cluster setup with seed nodes and
-credentials.
+While command-line tools such as curl, httpie, or wget work well for interacting with the API, a graphical
+interface (such as [Postman](https://www.postman.com/downloads/) or [Insomnia](https://insomnia.rest/)) is generally
+recommended for a more convenient and user-friendly experience.
 
-Request:
+### Backup
 
-```http
-GET {{baseUrl}}/v1/config/clusters
-```
-
-<details>
-    <summary>Response:</summary>
+#### Trigger On-Demand Backup
 
-<!-- ClustersResponse -->
+This request starts the backup operation for the specified routine, regardless of its configured schedule.
 
-```json
 [
-  {
-    "seed-nodes": [
-      {
-        "host-name": "host.docker.internal",
-        "port": 3000
-      }
-    ],
-    "credentials": {
-      "user": "user",
-      "password": "password"
-    }
-  }
-]
-```
+`POST {{baseUrl}}/v1/backups/schedule/<routineName>?delay=<timeout>`](https://aerospike.github.io/aerospike-backup-service/#/Backup/scheduleFullBackup)
 
-</details>
+* routineName: The name of the backup routine to trigger.
+* delay (optional): Time in milliseconds to delay the start of the backup.
 
-#### Get routine configuration
+If the request is accepted, the server responds with Http 202 Accepted.
 
-Retrieves the configured backup routines.
+#### Get Current Backup
 
-Request:
+This endpoint retrieves the current statistics for a backup in progress, identified by its routine name.
 
-```http
-GET {{baseUrl}}/v1/config/routines
-```
+[
+`GET {{baseUrl}}/v1/backups/currentBackup/<routineName>`](https://aerospike.github.io/aerospike-backup-service/#/Backup/getCurrentBackup)
+
+* routineName: The name of the routine for which to retrieve current backup information.
 
 <details>
-    <summary>Response:</summary>
+    <summary>Response</summary>
 
-<!-- RoutinesResponse -->
+<!-- CurrentBackupResponse -->
 
 ```json
 {
-  "routine1": {
-    "backup-policy": "keepFilesPolicy",
-    "source-cluster": "absDefaultCluster",
-    "storage": "local",
-    "interval-cron": "@yearly",
-    "namespaces": [
-      "test-namespace"
-    ]
-  },
-  "routine2": {
-    "backup-policy": "removeFilesPolicy",
-    "source-cluster": "absDefaultCluster",
-    "storage": "local",
-    "interval-cron": "@monthly",
-    "incr-interval-cron": "@daily",
-    "namespaces": [
-      "test-namespace"
-    ],
-    "set-list": [
-      "backupSet"
-    ],
-    "bin-list": [
-      "backupBin"
-    ]
+  "full": {
+    "total-records": 100000,
+    "done-records": 50000,
+    "start-time": "2024-01-01T12:00:00Z",
+    "percentage-done": 50,
+    "estimated-end-time": "2024-01-01T13:00:00Z",
+    "metrics": {
+      "records-per-second": 1000,
+      "kilobytes-per-second": 30000,
+      "pipeline": 0
+    }
   }
 }
 ```
 
-</details>
-
-#### Get storage configuration
-
-Returns all the configured storage endpoints, including, if applicable, cloud storage endpoint information such as
-region and path.
+`estimated-end-time` an estimation, is calculated based on the current percentage done and duration.
 
-Request:
+`records-per-second` and `kilobytes-per-second` show current speed, they are updated every second.
 
-```http
-GET {{baseUrl}}/v1/config/storage
-```
+`pipeline` represents the number of records that have been read from the source but not yet written to the
+destination.
+This metric helps identify bottlenecks:
 
-<details>
-    <summary>Response:</summary>
+- if Pipeline is zero or fluctuates near zero, it means the destination (storage) is consuming data faster than the
+  source (Aerospike) can read.
+- If Pipeline grows large, it indicates that the source is producing data faster than the destination can consume.
 
-<!-- StorageResponse -->
+</details>
 
-```json
-{
-  "aws-s3": {
-    "s3-storage": {
-      "bucket": "as-backup-bucket",
-      "path": "backups",
-      "s3-region": "eu-central-1"
-    }
-  },
-  "azure-blob-storage": {
-    "azure-storage": {
-      "endpoint": "http://127.0.0.1:6000/devstoreaccount1",
-      "container-name": "testcontainer",
-      "path": "backups",
-      "account-name": "devstoreaccount1",
-      "account-key": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
-    }
-  },
-  "gcp-gcs": {
-    "gcp-storage": {
-      "key-file-path": "key-file.json",
-      "bucket-name": "gcp-backup-bucket",
-      "path": "backups",
-      "endpoint": "http://127.0.0.1:9020"
-    }
-  },
-  "local": {
-    "local-storage": {
-      "path": "backups"
-    }
-  }
-}
-```
+#### Cancel Backup Job
 
-</details>
+[
+`POST {{baseUrl}}/v1/backups/cancel/<routineName>`](https://aerospike.github.io/aerospike-backup-service/#/Backup/cancelCurrentBackup)
 
-### Retrieve backup list
+Cancel all currently running backups (both full and incremental) for the specified routine. Partially created backups
+will be deleted.
 
-#### Full backup list
+#### Retrieve Backup List
 
-Provides a list of backups for each configured routine, including details such as creation time, namespace, and storage
+Provides a list of backups for each configured routine, including details such as creation time, duration, namespace,
+and storage
 location.
 
-Request:
-
-```http
-GET {{baseUrl}}/v1/backups/full
-```
+[`GET {{baseUrl}}/v1/backups/full`](https://aerospike.github.io/aerospike-backup-service/#/Backup/getFullBackups)
 
 <details>
-    <summary>Response:</summary>
+    <summary>Response</summary>
 
+Response is a map of routine names to lists of backups.
 <!-- FullBackupsResponse -->
 
 ```json
@@ -446,27 +409,37 @@ GET {{baseUrl}}/v1/backups/full
 
 </details>
 
-### Restore backup (direct restoration)
+It's possible to filter the results by adding query parameters:
 
-#### Direct restore using a specific backup
+[
+`GET {{baseUrl}}/v1/backups/full/<name>?from=<from>&to=<to>`](https://aerospike.github.io/aerospike-backup-service/#/Backup/getFullBackups)
 
-Destination field says where to restore to. It can be one of the clusters we read in 1st section, or any other Aerospike
-cluster.
+where `name` is the routine name, `from` and `to` are timestamps in milliseconds since epoch.
 
-This request restores a backup from a specified path to a designated destination.
-The `no-generation` parameter allows overwriting of existing keys if set to `true`.
+#### Disable Routine
 
-In the `source` section, `path` is the `key` value returned as a response in the [Full Backup List](#full-backup-list)
-example. The `type` parameter under `source` denotes S3 storage if set to `1` and local storage if set to `0`.
+[
+`POST {{baseUrl}}/v1/routines/<routineName>/disable/`](https://aerospike.github.io/aerospike-backup-service/#/Configuration/disableRoutine)
 
-Request:
+[
+`POST {{baseUrl}}/v1/routines/<routineName>/enable/`](https://aerospike.github.io/aerospike-backup-service/#/Configuration/enableRoutine)
 
-```http
-POST {{baseUrl}}/v1/restore/full
-```
+Set the disabled flag for the given routine to `true` or `false` (default is `false`).
+
+- Disabled routines will not schedule new jobs.
+- Running jobs will be canceled, similar to the `Cancel Backup Job` endpoint.
+
+### Restore
+
+#### Direct restore using a specific backup
+
+This request restores a backup from a specified path to a designated destination.
+
+[
+`POST {{baseUrl}}/v1/restore/full`](https://aerospike.github.io/aerospike-backup-service/#/Restore/restoreFull)
 
 <details>
-    <summary>Request body:</summary>
+    <summary>Request body</summary>
 
 <!-- RestoreFullRequest -->
 
@@ -498,52 +471,37 @@ POST {{baseUrl}}/v1/restore/full
 }
 ```
 
-</details>
+The `no-generation` parameter allows overwriting of existing keys if set to `true`.
 
-The response is a job ID. You can get job status with the
-endpoint [
-`GET {{baseUrl}}/v1/restore/status/:<jobId>`](https://aerospike.github.io/aerospike-backup-service/#/Restore/restoreStatus).
+In the `source` section, `path` is the `key` value returned as a response in the [Full Backup List](#full-backup-list)
+example. The `type` parameter under `source` denotes S3 storage if set to `1` and local storage if set to `0`.
 
-Response:
+`destination` field says where to restore to. It can be any Aerospike cluster.
 
-```json
-123456789
-```
+Alternatively, you can use `destination-name` and `storage-name` instead of `destination` and `storage` respectively.
+They
+refer to the names of the corresponding entities in the configuration file.
+
+</details>
+
+The response is a job ID.
 
 #### Restore using routine name and timestamp
 
 This option restores the most recent full backup for the given timestamp and then applies all subsequent incremental
-backups up to that timestamp.
-In this example, the `destination` and `policy` fields are the same as in the previous example.
-
-Request:
+backups up to that timestamp. You don't need to specify the exact backup path or storage.
 
-```http
-POST {{baseUrl}}/v1/restore/timestamp
-```
+[`
+POST {{baseUrl}}/v1/restore/timestamp`](https://aerospike.github.io/aerospike-backup-service/#/Restore/restoreTimestamp)
 
 <details>
-    <summary>Response:</summary>
+    <summary>Request</summary>
 
 <!-- RestoreTimestampRequest -->
 
 ```json
 {
-  "destination": {
-    "seed-nodes": [
-      {
-        "host-name": "host.docker.internal",
-        "port": 3000
-      }
-    ],
-    "credentials": {
-      "user": "user",
-      "password": "password"
-    }
-  },
-  "policy": {
-    "no-generation": true
-  },
+  "destination-name": "abs-cluster",
   "time": 1704110400000,
   "routine": "routine1"
 }
@@ -551,19 +509,187 @@ POST {{baseUrl}}/v1/restore/timestamp
 
 </details>
 
-The response is a job ID. You can get job status with the
-endpoint [
-`GET {{baseUrl}}/v1/restore/status/:<jobId>`](https://aerospike.github.io/aerospike-backup-service/#/Restore/restoreStatus).
+The response is a job ID.
+
+#### Restore job status
+
+You can get job status with the
+endpoint
+
+[
+`GET {{baseUrl}}/v1/restore/status/<jobId>`](https://aerospike.github.io/aerospike-backup-service/#/Restore/restoreStatus).
+
+<details>
+    <summary>Request</summary>
+
 
-Response:
+<!-- CurrentBackupResponse -->
 
 ```json
-123456789
+{
+  "full": {
+    "total-records": 100000,
+    "done-records": 50000,
+    "start-time": "2024-01-01T12:00:00Z",
+    "percentage-done": 50,
+    "estimated-end-time": "2024-01-01T13:00:00Z",
+    "metrics": {
+      "records-per-second": 1000,
+      "kilobytes-per-second": 30000,
+      "pipeline": 0
+    }
+  }
+}
 ```
 
-## Breaking API Changes (v2 → v3):
+</details>
+
+#### Cancel Restore Job
 
-### Storage Object
+Cancel the restore job identified by `<jobId>`. Data that has already been restored will remain intact.
+
+[
+`POST {{baseUrl}}/v1/restore/cancel/<jobId>`](https://aerospike.github.io/aerospike-backup-service/#/Restore/cancelRestore)
+
+# FAQ
+
+## What happens when a backup doesn’t finish before another starts (for the same routine)?
+
+- **Full Backups:**
+    - Full backups cannot overlap. If a scheduled full backup is due to start but the previous one is still running, the
+      new backup is skipped entirely. It is not queued but will wait for the next scheduled execution.
+    - Full backups always take priority over incremental backups. If an incremental backup is running when a full backup
+      is scheduled, the full backup will start as planned, and the incremental backup will continue running without
+      interruption.
+
+- **Incremental Backups:**
+    - By default, incremental backups are skipped if any other backup (full or incremental) is still running.
+      This behavior can be overridden using the [
+      `backup-policy.concurrent-incremental`](#concurrent-incremental-backups) setting, which allows incremental backups
+      to run concurrently.
+    - Incremental backups will not run until at least one full backup has been successfully completed.
+
+## Can multiple backup routines be performed simultaneously?
+
+Yes, multiple backup routines can run in parallel. Furthermore, it is possible to back up different namespaces from the
+same cluster using separate routines with different schedules, all running simultaneously.
+
+To manage resource utilization, you can configure the `cluster.max-parallel-scans` property to limit the number of read
+threads operating on a single cluster.
+
+## Which storage providers are supported?
+
+The backup service supports the following storage providers:
+
+- **AWS S3** (or compatible services such as MinIO)
+- **Microsoft Azure**
+- **Google Cloud Storage**
+- **Local storage** (files stored on the same machine where the backup service is running)
+
+# Build from source
+
+### Prerequisites
+
+- Go 1.23
+
+### Build the service
+
+The following command generates a binary under the `build/target` directory.
+
+```bash
+make build
+```
+
+### Build Docker image
+
+#### Multiplatform
+
+```bash
+DOCKER_USERNAME="<jforg-username>" DOCKER_PASSWORD="<jfrog-password>" TAG="<tag>" make docker-buildx 
+```
+
+#### For local use
+
+```bash
+TAG="<tag>" make docker-build
+```
+
+### Build Linux packages
+
+Run `make packages`.
+This will generate a `rpm/deb` package for supported platforms (`linux/amd64`,`linux/arm64`) with respective `sha256`
+checksum file in the `build/target` directory.
+See the quick [guide](build/package/README.md) on how to get started with the Linux packages.
+
+### Release
+
+Use the following commands before a release to update the version.
+
+```bash
+NEXT_VERSION="<version>"  make release
+NEXT_HELM_CHART_VERSION="<helm-chart-version>" make helm-chart-release
+git add --all
+git commit -m "Release: "$(cat VERSION)""
+git tag "$(cat VERSION)"
+git push 
+```
+
+# Migration Guide
+
+## v3 -> v3.1
+
+There is no breaking change in this release, but several new features have been introduced.
+
+#### Strict validation
+
+The backup service performs strict validation of the configuration file during startup.
+Invalid configurations will result in errors preventing the service from starting. This will help prevent unexpected
+behavior caused by invalid configurations.
+
+#### Filter by partition
+
+backup policy has new flag `partition-list`. When enabled, the backup service will back up only specific partitions of
+the
+cluster.
+The format supports individual partitions or ranges.
+
+- A range is specified as "<start>,<count>" (e.g., "100,50" backs up 50 partitions starting from 100).
+- A single partition is specified as a number (e.g., "0").
+- Multiple entries can be comma-separated: e.g., "0,100,200,300,400,500".
+
+By default, all partitions (0 to 4095) are backed up.
+This field is mutually exclusive with node-list.
+
+This feature can be used to parallelize backups across multiple instances. Each instance can be assigned a subset of
+partitions to back up, ensuring efficient distribution of workload.
+
+#### Support for specifying object storage classes
+
+Every storage provider now supports specifying an object storage class
+
+* `STANDARD`, `GLACIER`, `DEEP_ARCHIVE`etc for S3
+* `Hot`, `Cool`, `Cold`, `Archive` for Azure Blob Storage
+* `Standard`, `Nearline`, `Coldline`, `Archive` for Google Cloud Storage
+
+Object storage classes define the durability and availability levels for objects within a bucket.
+Supported values depend on the chosen storage provider.
+
+#### Concurrent incremental backups
+
+Backup policy has new flag `concurrent-incremental`.
+
+* When false (default), incremental backups are skipped if another backup for same routine is in progress.
+
+* When true, incremental backups can run concurrently with full backups for the same routine.
+
+#### Skip cluster config backup
+
+Backup policy has new field `with-cluster-configuration`.
+When false (default), the backup service will exclude cluster configuration from the backup.
+
+## v2 -> v3
+
+#### Storage Object
 
 The `Storage` object schema has been updated in **v3** to improve clarity, modularity, and support for additional
 storage types.
@@ -581,7 +707,7 @@ storage types.
 - **v2**: S3 paths were constructed as `s3://<bucket>/<path>`.
 - **v3**: `bucket` and `path` are now separate fields in `dto.S3Storage`.
 
-### **Example**
+Example:
 
 <!-- Storage -->
 
@@ -610,14 +736,14 @@ local:
 
 ```
 
-### Configuration Management Update
+#### Configuration Management Update
 
 Changes to the configuration API take effect immediately in version 3.0.
 
 Configuration changes in versions prior to 3.0 required an explicit "apply" step after CRUD operations to update the
 runtime configuration.
 
-#### Key Changes
+**Key Changes**
 
 - **Config Updates:** Each CRUD update now automatically saves the configuration to the file and applies it to the
   runtime system. No need for a separate "apply" operation.
@@ -627,15 +753,15 @@ runtime configuration.
     - If a routine entry is absent in the updated configuration file, it will not be rescheduled.
     - If the routine entry is updated, it will be rescheduled with the new parameters.
 
-### Apply Endpoint
+#### Apply Endpoint
 
 The `apply` endpoint reads and applies the configuration from the file (after it was modified externally).
 
-### Secret Agents
+#### Secret Agents
 
 The `secret-agent` configuration field to store the list of secret agents is now named `secret-agents`.
 
-### Restore Request
+#### Restore Request
 
 In the new version (v3) of the API, the **`restore`** request (`/v1/restore/full` and `/v1/restore/incremental`)
 was changed to simplify and streamline the process.
@@ -645,7 +771,7 @@ was changed to simplify and streamline the process.
   The specific backup data location is now specified using a new required field: **`backup-data-path`**.
   This change allows you to reuse the same storage for different restore requests.
 
-### Backup Retention Policy
+#### Backup Retention Policy
 
 This release introduces a new, configurable **RetentionPolicy** for managing backup storage more effectively.
 The feature allows users to specify retention rules for both full and incremental backups, replacing the previous
@@ -665,9 +791,7 @@ After each successfull full backup, all existing backups are scanned to count fu
 ABS then removes older full backups and their associated incremental backups as needed to retain only
 the last `full` backups and incremental backups for the most recent `incremental` backups.
 
-## New API functions (v2 → v3):
-
-### Node list
+#### Node list
 
 Backup routine has a new optional `node-list` property.
 
@@ -682,17 +806,18 @@ Back up the given cluster nodes only.
 This argument is mutually exclusive to partition-list/after-digest arguments.
 Default: back up all nodes in the cluster
 
-### Extra ttl
+##### Extra ttl
 
 A new optional field, `extra-ttl`, has been added to the restore policy configuration.
 It specifies the amount of extra time-to-live (TTL) to add to records that have expirable void-times.
 
-### Secret Agent for cluster
+#### Secret Agent for cluster
 
 The credential object has a new optional `secret-agent` property that points to a secret agent, one of those listed in
 the `secret-agents` configuration parameter.
 Secret agent is responsible for storing secrets like passwords and TLS certificates.
-`The password` field can contain either the password itself (recommended only for testing), or a path pointing to the password in the Aerospike Secret Agent (starts with `secrets:`).
+`The password` field can contain either the password itself (recommended only for testing), or a path pointing to the
+password in the Aerospike Secret Agent (starts with `secrets:`).
 
 The fields `password` and `password-path` are mutually exclusive.
 
@@ -734,37 +859,4 @@ dto.Credentials:
       example: testUser
       type: string
   type: object
-```
-
-### Cancel Restore Job
-
-New endpoint:
-
-- [
-  `POST {{baseUrl}}/v1/restore/cancel/:<jobId>`](https://aerospike.github.io/aerospike-backup-service/#/Restore/cancelRestore)
-
-Cancel the restore job identified by `<jobId>`. Data that has already been restored will remain intact.
-
-### Cancel Backup Job
-
-New endpoint:
-
-- [
-  `POST {{baseUrl}}/v1/backups/cancel/:<routineName>`](https://aerospike.github.io/aerospike-backup-service/#/Backup/cancelCurrentBackup)
-
-Cancel all currently running backups (both full and incremental) for the specified routine. Partially created backups
-will be deleted.
-
-### Disable Routine
-
-New endpoints:
-
-- [
-  `POST {{baseUrl}}/v1/routines/:<routineName>/disable/`](https://aerospike.github.io/aerospike-backup-service/#/Configuration/disableRoutine)
-- [
-  `POST {{baseUrl}}/v1/routines/:<routineName>/enable/`](https://aerospike.github.io/aerospike-backup-service/#/Configuration/enableRoutine)
-
-Set the disabled flag for the given routine to `true` or `false` (default is `false`).
-
-- Disabled routines will not schedule new jobs.
-- Running jobs will be canceled, similar to the `Cancel Backup Job` endpoint.
\ No newline at end of file
+```
\ No newline at end of file
diff --git a/build/package/config/aerospike-backup-service.yml b/build/package/config/aerospike-backup-service.yml
index 316010de8..ba086c9f3 100644
--- a/build/package/config/aerospike-backup-service.yml
+++ b/build/package/config/aerospike-backup-service.yml
@@ -1,30 +1,44 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/aerospike/aerospike-backup-service/refs/tags/v3.1.0/docs/config.schema.json
 ---
-# This is sample config
 aerospike-clusters:
-  cluster:
-    use-services-alternate: false
+  abs-cluster: # <--- Custom cluster name
     seed-nodes:
-      - host-name: "127.0.0.1"
+      - host-name: localhost
         port: 3000
     credentials:
-      user: "admin"
-      password: "admin"
+      user: tester
+      password: secret:asbackup:psw # Password will be fetched from the secret agent
+      secret-agent-name: secret-agent  # <--- Refers to the secret agent name under secret-agents
+
+secret-agents:
+  secret-agent: # <--- Custom secret agent name
+    address: localhost
+    port: 5000
+    connection-type: tcp
 
 storage:
-  local:
-    local-storage:
-      path: "/var/lib/aerospike-backup-service"
+  s3: # <--- Custom storage name
+    s3-storage: # Storage type; can be one of "local-storage", "s3-storage", "azure-storage", "gcp-storage"
+      path: backups
+      bucket: as-backup-bucket
+      s3-region: eu-central-1
+      min-part-size: 50_000_000 # Upload chunk size in bytes (May affect performance)
 
 backup-policies:
-  policy:
-    parallel: 1
-
+  dailyBackupPolicy: # <--- Custom policy name
+    parallel: 8 # Parallelism level (May affect performance)
+    file-limit: 1000 # Max backup file size in MB (May affect performance)
+    compression: # Backup files will be compressed before uploading (May affect performance)
+      mode: ZSTD
+      level: 1
+    retention:
+      full: 10 # Retain 10 full backups
+      incremental: 5 # Retain incremental backups for the 5 latest full backups
 
 backup-routines:
-  routine:
-    interval-cron: "1/30 * * * * *" # every 30 seconds
-    incr-interval-cron: "1/5 * * * * *" # every 5 seconds
-    backup-policy: "policy"
-    source-cluster: "cluster"
-    storage: "local"
-    namespace: "test"
+  dailyLocalBackupRoutine: # <--- Custom routine name
+    interval-cron: "@daily" # Full backup will be triggered daily at midnight
+    incr-interval-cron: "0 */2 * * * *" # Incremental backups every 2 hours
+    source-cluster: abs-cluster         # <--- Refers to the cluster name under aerospike-clusters
+    storage: s3                         # <--- Refers to the storage name under storage
+    backup-policy: dailyBackupPolicy    # <--- Refers to the policy name under backup-policies
\ No newline at end of file
diff --git a/build/readme/readme_example_generator.go b/build/readme/readme_example_generator.go
index bd12c49c2..673826ec3 100644
--- a/build/readme/readme_example_generator.go
+++ b/build/readme/readme_example_generator.go
@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/aerospike/aerospike-backup-service/v3/pkg/dto"
+	"github.com/aerospike/aerospike-backup-service/v3/pkg/dto/decoder"
 	"github.com/aerospike/aerospike-backup-service/v3/pkg/util"
 	"gopkg.in/yaml.v3"
 )
@@ -124,22 +125,68 @@ var jsonExamples = map[string]any{
 	},
 	"RestoreTimestampRequest": dto.RestoreTimestampRequest{
 		DestinationClusterConfig: dto.DestinationClusterConfig{
-			Cluster: &cluster,
-		},
-		Policy: &dto.RestorePolicy{
-			NoGeneration: util.Ptr(true),
+			Name: "abs-cluster",
 		},
 		Time:    1704110400000,
 		Routine: "routine1",
 	},
+	"CurrentBackupResponse": dto.RoutineState{
+		Full: &dto.RunningJob{
+			TotalRecords:     100_000,
+			DoneRecords:      50_000,
+			StartTime:        time.Date(2024, 01, 01, 12, 0, 0, 0, time.UTC),
+			FinishTime:       nil,
+			PercentageDone:   50,
+			EstimatedEndTime: util.Ptr(time.Date(2024, 01, 01, 13, 0, 0, 0, time.UTC)),
+			Metrics: dto.Metrics{
+				RecordsPerSecond:   1000,
+				KilobytesPerSecond: 30000,
+				Pipeline:           0,
+			},
+		},
+	},
+	"CurrentRestoreResponse": dto.RestoreJobStatus{
+		ReadRecords:     100_000,
+		TotalBytes:      30000000,
+		ExpiredRecords:  0,
+		SkippedRecords:  0,
+		IgnoredRecords:  0,
+		InsertedRecords: 5_000,
+		ExistedRecords:  0,
+		FresherRecords:  0,
+		IndexCount:      4,
+		UDFCount:        1,
+		ErrorsInDoubt:   0,
+		CurrentRestore: &dto.RunningJob{
+			TotalRecords:     100_000,
+			DoneRecords:      50_000,
+			StartTime:        time.Date(2024, 01, 01, 12, 0, 0, 0, time.UTC),
+			FinishTime:       nil,
+			PercentageDone:   50,
+			EstimatedEndTime: util.Ptr(time.Date(2024, 01, 01, 13, 0, 0, 0, time.UTC)),
+			Metrics: dto.Metrics{
+				RecordsPerSecond:   1000,
+				KilobytesPerSecond: 30000,
+				Pipeline:           0,
+			},
+		},
+		Status: dto.JobStatusRunning,
+		Error:  "",
+	},
 }
 
 var yamlExamples = map[string]any{
 	"Storage": allStorageTypes,
+	"RemoteConfig": dto.Storage{
+		S3Storage: &dto.S3Storage{
+			Path:     "config.yml",
+			Bucket:   "as-backup-bucket",
+			S3Region: "eu-central-1",
+		},
+	},
 }
 
 func main() {
-	_ = dto.AerospikeCluster{}
 	readme, err := os.ReadFile("README.md")
 	if err != nil {
 		panic(err)
@@ -152,31 +199,29 @@ func main() {
 	updatedReadme := re.ReplaceAllFunc(readme, func(match []byte) []byte {
 		submatches := re.FindSubmatch(match)
 		if len(submatches) < 3 {
-			return match
+			panic(fmt.Errorf("failed to find submatch: %s", submatches))
 		}
 
 		name := string(submatches[1])
 		format := string(submatches[2])
 
-		var example any
-		var exists bool
 		var formattedExample []byte
 
 		switch format {
 		case "json":
-			example, exists = jsonExamples[name]
+			example, exists := jsonExamples[name]
 			if exists {
 				formattedExample, err = json.MarshalIndent(example, "", "  ")
 			}
 		case "yaml":
-			example, exists = yamlExamples[name]
+			example, exists := yamlExamples[name]
 			if exists {
 				formattedExample, err = marshalYAML(example)
 			}
 		}
 
-		if !exists || err != nil {
-			return match
+		if err != nil {
+			panic(fmt.Errorf("failed to parse: %w", err))
 		}
 
 		var buffer bytes.Buffer
@@ -186,12 +231,37 @@ func main() {
 
 		return buffer.Bytes()
 	})
+
+	updatedReadme = updateDefaultConfigSection(updatedReadme)
+
 	err = os.WriteFile("README.md", updatedReadme, 0600)
 	if err != nil {
 		panic(err)
 	}
 }
 
+func updateDefaultConfigSection(readme []byte) []byte {
+	configRe := regexp.MustCompile("<!--\\s*DefaultConfig\\s*-->\\s*```yaml[\\s\\S]*?```")
+
+	configContent, err := os.ReadFile("build/package/config/aerospike-backup-service.yml")
+	if err != nil {
+		panic(fmt.Errorf("failed to read config YAML: %w", err))
+	}
+
+	_, err = dto.NewConfigFromReader(bytes.NewReader(configContent), decoder.YAML)
+	if err != nil {
+		panic(fmt.Errorf("failed to parse default config YAML: %w", err))
+	}
+
+	return configRe.ReplaceAllFunc(readme, func(_ []byte) []byte {
+		var buffer bytes.Buffer
+		buffer.WriteString("<!-- DefaultConfig -->\n\n```yaml\n")
+		buffer.Write(configContent)
+		buffer.WriteString("\n```")
+		return buffer.Bytes()
+	})
+}
+
 // MarshalYAML marshals the input into YAML and replaces 4-space indents with 2-space indents.
 // we need this to be in sync with Goland's markdown formatter.
 func marshalYAML(v interface{}) ([]byte, error) {
diff --git a/build/scripts/readme-toc.sh b/build/scripts/readme-toc.sh
new file mode 100644
index 000000000..eab81ccd4
--- /dev/null
+++ b/build/scripts/readme-toc.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+# This script updates the Table of Contents in the README.md file.
+
+# Check if markdown-toc is installed
+if ! command -v markdown-toc >/dev/null 2>&1; then
+  echo "markdown-toc not found. Installing via Homebrew..."
+  brew install markdown-toc
+fi
+
+# Find the root of the Git workspace
+WORKSPACE="$(git rev-parse --show-toplevel)"
+
+# Update the README.md with a table of contents
+markdown-toc -i "$WORKSPACE/README.md" --maxdepth 3
\ No newline at end of file
diff --git a/cmd/backup/main.go b/cmd/backup/main.go
index f42369646..c2756f74d 100644
--- a/cmd/backup/main.go
+++ b/cmd/backup/main.go
@@ -44,7 +44,7 @@ func run() int {
 	}
 
 	rootCmd := &cobra.Command{
-		Use:     "Use the following properties for service configuration",
+		Use:     "aerospike-backup-service",
 		Short:   "Aerospike Backup Service",
 		Version: backup.Version,
 		PreRunE: validateFlags,
diff --git a/docs/config.schema.json b/docs/config.schema.json
index 83673a9dc..257075c53 100644
--- a/docs/config.schema.json
+++ b/docs/config.schema.json
@@ -56,7 +56,7 @@
             "type": "object"
           },
           "label": {
-            "description": "The cluster name.",
+            "description": "The cluster name. Optional: used only in logs and error messages.",
             "example": "testCluster",
             "type": "string"
           },
@@ -86,6 +86,9 @@
             "type": "boolean"
           }
         },
+        "required": [
+          "seed-nodes"
+        ],
         "type": "object"
       },
       "dto.AzureStorage": {
@@ -257,7 +260,7 @@
         "description": "BackupPolicy represents a scheduled backup policy.",
         "properties": {
           "bandwidth": {
-            "description": "Throttles backup write operations to the backup file(s) to not exceed the given\nbandwidth in MiB/s.",
+            "description": "Throttles backup write speed to a maximum of the specified bandwidth in MiB/s.\nDefault is no limit.",
             "example": 10000,
             "type": "integer"
           },
@@ -267,7 +270,7 @@
                 "$ref": "#/components/schemas/dto.CompressionPolicy"
               }
             ],
-            "description": "Compression details.",
+            "description": "Compression details (algorithm and mode). Default is no compression.\nEnabling compression reduces storage and network usage, but increases CPU usage during the backup.\nDepending on the system configuration, compression may improve or degrade overall performance.",
             "type": "object"
           },
           "concurrent-incremental": {
@@ -280,11 +283,11 @@
                 "$ref": "#/components/schemas/dto.EncryptionPolicy"
               }
             ],
-            "description": "Encryption details.",
+            "description": "Encryption details (algorithm and key). Default is no encryption.",
             "type": "object"
           },
           "file-limit": {
-            "description": "File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,\na new backup file will be created.",
+            "description": "File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,\na new backup file will be created. Default is 250 MB.",
             "example": 1024,
             "type": "integer"
           },
@@ -301,12 +304,12 @@
             "type": "boolean"
           },
           "parallel": {
-            "description": "Maximum number of scan calls to run in parallel.",
+            "description": "Maximum number of scan calls to run in parallel. Each scan call processes a subset of the total\ndata partitions. The optimal value depends on hardware and network configuration.\nDefault: 8.",
             "example": 1,
             "type": "integer"
           },
           "records-per-second": {
-            "description": "Limit total returned records per second (RPS). If RPS is zero (the default),\nthe records-per-second limit is not applied.",
+            "description": "Limits the number of records returned per second (RPS). Default is no limit.",
             "example": 1000,
             "type": "integer"
           },
@@ -316,7 +319,7 @@
                 "$ref": "#/components/schemas/dto.RetentionPolicy"
               }
             ],
-            "description": "Specifies how long to retain full and incremental backups.",
+            "description": "Specifies how long to retain full and incremental backups.\nCleanup runs asynchronously after each successful full backup, never deleting backups preemptively.\nEnsure storage capacity for at least one extra full backup beyond the retention configuration.",
             "type": "object"
           },
           "retry-policy": {
@@ -325,7 +328,7 @@
                 "$ref": "#/components/schemas/dto.RetryPolicy"
               }
             ],
-            "description": "RetryPolicy defines the configuration for retry attempts in case of failures.\nIf nil, default policy is used.",
+            "description": "RetryPolicy defines the configuration for database scan retry attempts in case of failures.\nIf nil, the default policy is used (5 retries with a one-minute delay between attempts).",
             "type": "object"
           },
           "sealed": {
@@ -333,7 +336,7 @@
             "type": "boolean"
           },
           "socket-timeout": {
-            "description": "Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
+            "description": "Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
             "example": 1000,
             "type": "integer"
           },
@@ -353,8 +356,7 @@
         "description": "BackupRoutine represents a scheduled backup operation routine.",
         "properties": {
           "backup-policy": {
-            "description": "The name of the corresponding backup policy.",
-            "example": "keepAllPolicy",
+            "description": "The name of the corresponding backup policy (optional).",
             "type": "string"
           },
           "bin-list": {
@@ -368,7 +370,7 @@
             "type": "array"
           },
           "disabled": {
-            "description": "Whether this routine is disabled and should not run.",
+            "description": "Whether this routine is disabled and should not run. Default: false.",
             "type": "boolean"
           },
           "incr-interval-cron": {
@@ -377,7 +379,7 @@
             "type": "string"
           },
           "interval-cron": {
-            "description": "The interval for full backup as a cron expression string.",
+            "description": "The interval for full backup as a cron expression string.\nCron expression format: https://github.com/reugn/go-quartz?tab=readme-ov-file#cron-expression-format",
             "example": "0 0 * * * *",
             "type": "string"
           },
@@ -392,24 +394,18 @@
             "type": "array"
           },
           "node-list": {
-            "description": "NodeList contains a list of nodes to back up.\nBackup the given cluster nodes only.\nIf it is set, ParallelNodes automatically set to true.\nThis argument is mutually exclusive to partition-list/AfterDigest arguments.",
-            "example": [
-              "<IP addr 1>:<port 1>[",
-              "<IP addr 2>:<port 2>[",
-              "...]]"
-            ],
+            "description": "NodeList specifies which Aerospike nodes to include in the backup.\nOnly the listed nodes will be backed up.\nEach node can be specified as one of the following:\n- \"<IP address>:<port>\"\n- \"<hostname>:<port>\"\n- \"<node ID>\"\nTo obtain node identifiers, run: `asinfo -v \"service:\"`.\nIf using IP addresses or hostnames, ensure they match the values returned by the `asinfo` command.\nThis field is mutually exclusive with partition-list.\nParallelism is determined by the number of listed nodes unless `BackupPolicy.Parallel` is set to a lower value.",
             "items": {
               "type": "string"
             },
             "type": "array"
           },
           "partition-list": {
-            "description": "Back up list of partition filters. Partition filters can be ranges or individual partitions.\nRange is a pair of partition number and count.\nExample: \"0,100-50\" will backup partitions 0 and 50 partitions starting 100.\nDefault number of partitions to back up: 0 to 4095: all partitions.",
-            "example": "0-1000",
+            "description": "PartitionList defines the list of partitions to include in the backup.\nThe format supports individual partitions or ranges.\n- A range is specified as \"<start>,<count>\" (e.g., \"100,50\" backs up 50 partitions starting from 100).\n- A single partition is specified as a number (e.g., \"0\").\nMultiple entries can be comma-separated: e.g., \"0,100,200,300,400,500\".\nBy default, all partitions (0 to 4095) are backed up.\nThis field is mutually exclusive with node-list.",
             "type": "string"
           },
           "prefer-racks": {
-            "description": "A list of Aerospike Server rack IDs to prefer when reading records for a backup.",
+            "description": "PreferRacks specifies a list of Aerospike Server rack IDs to prioritize when reading records during backup.\nThis is optional and can be used to optimize for rack-aware deployments.",
             "example": [
               0
             ],
@@ -875,12 +871,12 @@
         "description": "RestoreNamespace specifies an alternative namespace name for the restore operation.",
         "properties": {
           "destination": {
-            "description": "Destination namespace name.",
+            "description": "Name of the destination namespace to restore data into.",
             "example": "destination-ns",
             "type": "string"
           },
           "source": {
-            "description": "Original namespace name.",
+            "description": "Original namespace name.\nThis field is required as a safeguard to ensure intentional namespace remapping.",
             "example": "source-ns",
             "type": "string"
           }
@@ -900,7 +896,7 @@
             "type": "integer"
           },
           "batch-size": {
-            "description": "The max allowed number of records per an async batch write call.\nDefault is 128 with batch writes enabled, or 16 without batch writes.",
+            "description": "The max allowed number of records per an async batch write call.\nOnly applicable when using batch writes.\nDefault: 128.",
             "example": 128,
             "type": "integer"
           },
@@ -921,7 +917,7 @@
                 "$ref": "#/components/schemas/dto.CompressionPolicy"
               }
             ],
-            "description": "Compression details.",
+            "description": "Compression details (algorithm). Default is no compression.",
             "type": "object"
           },
           "disable-batch-writes": {
@@ -934,7 +930,7 @@
                 "$ref": "#/components/schemas/dto.EncryptionPolicy"
               }
             ],
-            "description": "Encryption details.",
+            "description": "Encryption details (algorithm and key). Default is no encryption.",
             "type": "object"
           },
           "extra-ttl": {
@@ -953,7 +949,7 @@
                 "$ref": "#/components/schemas/dto.RestoreNamespace"
               }
             ],
-            "description": "Namespace details for the restore operation.\nBy default, the data is restored to the namespace from which it was taken.",
+            "description": "Namespace optionally specifies an alternative namespace name for the restore operation.\nBy default, the data is restored to the namespace from which it was taken.",
             "type": "object"
           },
           "no-generation": {
@@ -965,7 +961,7 @@
             "type": "boolean"
           },
           "no-records": {
-            "description": "Do not restore any record data (metadata or bin data).\nBy default, record data, secondary index definitions, and UDF modules\nwill be restored.",
+            "description": "Do not restore any record data (metadata or bin data).\nBy default, record data, secondary index definitions, and UDF modules will be restored.",
             "type": "boolean"
           },
           "no-udfs": {
@@ -973,7 +969,7 @@
             "type": "boolean"
           },
           "parallel": {
-            "description": "The number of concurrent record readers from backup files.",
+            "description": "The number of concurrent record readers from backup files.\nThis value controls the level of parallelism used by the backup service when\nreading backup files.\nThe optimal value depends on hardware and network configuration.\nDefault: 8.",
             "example": 8,
             "type": "integer"
           },
@@ -987,7 +983,7 @@
                 "$ref": "#/components/schemas/dto.RetryPolicy"
               }
             ],
-            "description": "Configuration of retries for each restore write operation.\nIf nil, default retry policy will be used.",
+            "description": "Configuration of retries for each restore write operation.\nIf nil, the default policy is used (5 retries with a one-minute delay between attempts).",
             "type": "object"
           },
           "set-list": {
@@ -1002,7 +998,7 @@
             "type": "array"
           },
           "socket-timeout": {
-            "description": "Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.\nSocket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
+            "description": "Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.\nSocket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
             "example": 1000,
             "type": "integer"
           },
@@ -1415,6 +1411,8 @@
           "port": {
             "description": "The port of the node.",
             "example": 3000,
+            "maximum": 65535,
+            "minimum": 1,
             "type": "integer"
           },
           "tls-name": {
diff --git a/docs/docs.go b/docs/docs.go
index d00a1f6d7..22b42f888 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -1600,6 +1600,9 @@ const docTemplate = `{
         "dto.AerospikeCluster": {
             "description": "AerospikeCluster represents the configuration for an Aerospike cluster for backup.",
             "type": "object",
+            "required": [
+                "seed-nodes"
+            ],
             "properties": {
                 "conn-timeout": {
                     "description": "The connection timeout in milliseconds.",
@@ -1615,7 +1618,7 @@ const docTemplate = `{
                     ]
                 },
                 "label": {
-                    "description": "The cluster name.",
+                    "description": "The cluster name. Optional: used only in logs and error messages.",
                     "type": "string",
                     "example": "testCluster"
                 },
@@ -1812,12 +1815,12 @@ const docTemplate = `{
             "type": "object",
             "properties": {
                 "bandwidth": {
-                    "description": "Throttles backup write operations to the backup file(s) to not exceed the given\nbandwidth in MiB/s.",
+                    "description": "Throttles backup write speed to a maximum of the specified bandwidth in MiB/s.\nDefault is no limit.",
                     "type": "integer",
                     "example": 10000
                 },
                 "compression": {
-                    "description": "Compression details.",
+                    "description": "Compression details (algorithm and mode). Default is no compression.\nEnabling compression reduces storage and network usage, but increases CPU usage during the backup.\nDepending on the system configuration, compression may improve or degrade overall performance.",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.CompressionPolicy"
@@ -1829,7 +1832,7 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "encryption": {
-                    "description": "Encryption details.",
+                    "description": "Encryption details (algorithm and key). Default is no encryption.",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.EncryptionPolicy"
@@ -1837,7 +1840,7 @@ const docTemplate = `{
                     ]
                 },
                 "file-limit": {
-                    "description": "File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,\na new backup file will be created.",
+                    "description": "File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,\na new backup file will be created. Default is 250 MB.",
                     "type": "integer",
                     "example": 1024
                 },
@@ -1854,17 +1857,17 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "parallel": {
-                    "description": "Maximum number of scan calls to run in parallel.",
+                    "description": "Maximum number of scan calls to run in parallel. Each scan call processes a subset of the total\ndata partitions. The optimal value depends on hardware and network configuration.\nDefault: 8.",
                     "type": "integer",
                     "example": 1
                 },
                 "records-per-second": {
-                    "description": "Limit total returned records per second (RPS). If RPS is zero (the default),\nthe records-per-second limit is not applied.",
+                    "description": "Limits the number of records returned per second (RPS). Default is no limit.",
                     "type": "integer",
                     "example": 1000
                 },
                 "retention": {
-                    "description": "Specifies how long to retain full and incremental backups.",
+                    "description": "Specifies how long to retain full and incremental backups.\nCleanup runs asynchronously after each successful full backup, never deleting backups preemptively.\nEnsure storage capacity for at least one extra full backup beyond the retention configuration.",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.RetentionPolicy"
@@ -1872,7 +1875,7 @@ const docTemplate = `{
                     ]
                 },
                 "retry-policy": {
-                    "description": "RetryPolicy defines the configuration for retry attempts in case of failures.\nIf nil, default policy is used.",
+                    "description": "RetryPolicy defines the configuration for database scan retry attempts in case of failures.\nIf nil, the default policy is used (5 retries with a one-minute delay between attempts).",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.RetryPolicy"
@@ -1884,7 +1887,7 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "socket-timeout": {
-                    "description": "Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
+                    "description": "Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
                     "type": "integer",
                     "example": 1000
                 },
@@ -1909,9 +1912,8 @@ const docTemplate = `{
             ],
             "properties": {
                 "backup-policy": {
-                    "description": "The name of the corresponding backup policy.",
-                    "type": "string",
-                    "example": "keepAllPolicy"
+                    "description": "The name of the corresponding backup policy (optional).",
+                    "type": "string"
                 },
                 "bin-list": {
                     "description": "The list of backup bin names (optional, an empty list implies backing up all bins).",
@@ -1924,7 +1926,7 @@ const docTemplate = `{
                     ]
                 },
                 "disabled": {
-                    "description": "Whether this routine is disabled and should not run.",
+                    "description": "Whether this routine is disabled and should not run. Default: false.",
                     "type": "boolean"
                 },
                 "incr-interval-cron": {
@@ -1933,7 +1935,7 @@ const docTemplate = `{
                     "example": "*/10 * * * * *"
                 },
                 "interval-cron": {
-                    "description": "The interval for full backup as a cron expression string.",
+                    "description": "The interval for full backup as a cron expression string.\nCron expression format: https://github.com/reugn/go-quartz?tab=readme-ov-file#cron-expression-format",
                     "type": "string",
                     "example": "0 0 * * * *"
                 },
@@ -1948,24 +1950,18 @@ const docTemplate = `{
                     ]
                 },
                 "node-list": {
-                    "description": "NodeList contains a list of nodes to back up.\nBackup the given cluster nodes only.\nIf it is set, ParallelNodes automatically set to true.\nThis argument is mutually exclusive to partition-list/AfterDigest arguments.",
+                    "description": "NodeList specifies which Aerospike nodes to include in the backup.\nOnly the listed nodes will be backed up.\nEach node can be specified as one of the following:\n- \"\u003cIP address\u003e:\u003cport\u003e\"\n- \"\u003chostname\u003e:\u003cport\u003e\"\n- \"\u003cnode ID\u003e\"\nTo obtain node identifiers, run: ` + "`" + `asinfo -v \"service:\"` + "`" + `.\nIf using IP addresses or hostnames, ensure they match the values returned by the ` + "`" + `asinfo` + "`" + ` command.\nThis field is mutually exclusive with partition-list.\nParallelism is determined by the number of listed nodes unless ` + "`" + `BackupPolicy.Parallel` + "`" + ` is set to a lower value.",
                     "type": "array",
                     "items": {
                         "type": "string"
-                    },
-                    "example": [
-                        "\u003cIP addr 1\u003e:\u003cport 1\u003e[",
-                        "\u003cIP addr 2\u003e:\u003cport 2\u003e[",
-                        "...]]"
-                    ]
+                    }
                 },
                 "partition-list": {
-                    "description": "Back up list of partition filters. Partition filters can be ranges or individual partitions.\nRange is a pair of partition number and count.\nExample: \"0,100-50\" will backup partitions 0 and 50 partitions starting 100.\nDefault number of partitions to back up: 0 to 4095: all partitions.",
-                    "type": "string",
-                    "example": "0-1000"
+                    "description": "PartitionList defines the list of partitions to include in the backup.\nThe format supports individual partitions or ranges.\n- A range is specified as \"\u003cstart\u003e,\u003ccount\u003e\" (e.g., \"100,50\" backs up 50 partitions starting from 100).\n- A single partition is specified as a number (e.g., \"0\").\nMultiple entries can be comma-separated: e.g., \"0,100,200,300,400,500\".\nBy default, all partitions (0 to 4095) are backed up.\nThis field is mutually exclusive with node-list.",
+                    "type": "string"
                 },
                 "prefer-racks": {
-                    "description": "A list of Aerospike Server rack IDs to prefer when reading records for a backup.",
+                    "description": "PreferRacks specifies a list of Aerospike Server rack IDs to prioritize when reading records during backup.\nThis is optional and can be used to optimize for rack-aware deployments.",
                     "type": "array",
                     "items": {
                         "type": "integer"
@@ -2469,12 +2465,12 @@ const docTemplate = `{
             ],
             "properties": {
                 "destination": {
-                    "description": "Destination namespace name.",
+                    "description": "Name of the destination namespace to restore data into.",
                     "type": "string",
                     "example": "destination-ns"
                 },
                 "source": {
-                    "description": "Original namespace name.",
+                    "description": "Original namespace name.\nThis field is required as a safeguard to ensure intentional namespace remapping.",
                     "type": "string",
                     "example": "source-ns"
                 }
@@ -2490,7 +2486,7 @@ const docTemplate = `{
                     "example": 50000
                 },
                 "batch-size": {
-                    "description": "The max allowed number of records per an async batch write call.\nDefault is 128 with batch writes enabled, or 16 without batch writes.",
+                    "description": "The max allowed number of records per an async batch write call.\nOnly applicable when using batch writes.\nDefault: 128.",
                     "type": "integer",
                     "example": 128
                 },
@@ -2506,7 +2502,7 @@ const docTemplate = `{
                     ]
                 },
                 "compression": {
-                    "description": "Compression details.",
+                    "description": "Compression details (algorithm). Default is no compression.",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.CompressionPolicy"
@@ -2518,7 +2514,7 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "encryption": {
-                    "description": "Encryption details.",
+                    "description": "Encryption details (algorithm and key). Default is no encryption.",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.EncryptionPolicy"
@@ -2536,7 +2532,7 @@ const docTemplate = `{
                     "example": 32
                 },
                 "namespace": {
-                    "description": "Namespace details for the restore operation.\nBy default, the data is restored to the namespace from which it was taken.",
+                    "description": "Namespace optionally specifies an alternative namespace name for the restore operation.\nBy default, the data is restored to the namespace from which it was taken.",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.RestoreNamespace"
@@ -2552,7 +2548,7 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "no-records": {
-                    "description": "Do not restore any record data (metadata or bin data).\nBy default, record data, secondary index definitions, and UDF modules\nwill be restored.",
+                    "description": "Do not restore any record data (metadata or bin data).\nBy default, record data, secondary index definitions, and UDF modules will be restored.",
                     "type": "boolean"
                 },
                 "no-udfs": {
@@ -2560,7 +2556,7 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "parallel": {
-                    "description": "The number of concurrent record readers from backup files.",
+                    "description": "The number of concurrent record readers from backup files.\nThis value controls the level of parallelism used by the backup service when\nreading backup files.\nThe optimal value depends on hardware and network configuration.\nDefault: 8.",
                     "type": "integer",
                     "example": 8
                 },
@@ -2569,7 +2565,7 @@ const docTemplate = `{
                     "type": "boolean"
                 },
                 "retry-policy": {
-                    "description": "Configuration of retries for each restore write operation.\nIf nil, default retry policy will be used.",
+                    "description": "Configuration of retries for each restore write operation.\nIf nil, the default policy is used (5 retries with a one-minute delay between attempts).",
                     "allOf": [
                         {
                             "$ref": "#/definitions/dto.RetryPolicy"
@@ -2588,7 +2584,7 @@ const docTemplate = `{
                     ]
                 },
                 "socket-timeout": {
-                    "description": "Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.\nSocket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
+                    "description": "Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.\nSocket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
                     "type": "integer",
                     "example": 1000
                 },
@@ -2993,6 +2989,8 @@ const docTemplate = `{
                 "port": {
                     "description": "The port of the node.",
                     "type": "integer",
+                    "maximum": 65535,
+                    "minimum": 1,
                     "example": 3000
                 },
                 "tls-name": {
diff --git a/docs/openapi.json b/docs/openapi.json
index 6c7dd6c91..6d6841b81 100644
--- a/docs/openapi.json
+++ b/docs/openapi.json
@@ -1833,7 +1833,7 @@
             "type" : "object"
           },
           "label" : {
-            "description" : "The cluster name.",
+            "description" : "The cluster name. Optional: used only in logs and error messages.",
             "example" : "testCluster",
             "type" : "string"
           },
@@ -1861,6 +1861,7 @@
             "type" : "boolean"
           }
         },
+        "required" : [ "seed-nodes" ],
         "type" : "object"
       },
       "dto.AzureStorage" : {
@@ -2023,7 +2024,7 @@
         "description" : "BackupPolicy represents a scheduled backup policy.",
         "properties" : {
           "bandwidth" : {
-            "description" : "Throttles backup write operations to the backup file(s) to not exceed the given\nbandwidth in MiB/s.",
+            "description" : "Throttles backup write speed to a maximum of the specified bandwidth in MiB/s.\nDefault is no limit.",
             "example" : 10000,
             "type" : "integer"
           },
@@ -2031,7 +2032,7 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.CompressionPolicy"
             } ],
-            "description" : "Compression details.",
+            "description" : "Compression details (algorithm and mode). Default is no compression.\nEnabling compression reduces storage and network usage, but increases CPU usage during the backup.\nDepending on the system configuration, compression may improve or degrade overall performance.",
             "type" : "object"
           },
           "concurrent-incremental" : {
@@ -2042,11 +2043,11 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.EncryptionPolicy"
             } ],
-            "description" : "Encryption details.",
+            "description" : "Encryption details (algorithm and key). Default is no encryption.",
             "type" : "object"
           },
           "file-limit" : {
-            "description" : "File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,\na new backup file will be created.",
+            "description" : "File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,\na new backup file will be created. Default is 250 MB.",
             "example" : 1024,
             "type" : "integer"
           },
@@ -2063,12 +2064,12 @@
             "type" : "boolean"
           },
           "parallel" : {
-            "description" : "Maximum number of scan calls to run in parallel.",
+            "description" : "Maximum number of scan calls to run in parallel. Each scan call processes a subset of the total\ndata partitions. The optimal value depends on hardware and network configuration.\nDefault: 8.",
             "example" : 1,
             "type" : "integer"
           },
           "records-per-second" : {
-            "description" : "Limit total returned records per second (RPS). If RPS is zero (the default),\nthe records-per-second limit is not applied.",
+            "description" : "Limits the number of records returned per second (RPS). Default is no limit.",
             "example" : 1000,
             "type" : "integer"
           },
@@ -2076,14 +2077,14 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.RetentionPolicy"
             } ],
-            "description" : "Specifies how long to retain full and incremental backups.",
+            "description" : "Specifies how long to retain full and incremental backups.\nCleanup runs asynchronously after each successful full backup, never deleting backups preemptively.\nEnsure storage capacity for at least one extra full backup beyond the retention configuration.",
             "type" : "object"
           },
           "retry-policy" : {
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.RetryPolicy"
             } ],
-            "description" : "RetryPolicy defines the configuration for retry attempts in case of failures.\nIf nil, default policy is used.",
+            "description" : "RetryPolicy defines the configuration for database scan retry attempts in case of failures.\nIf nil, the default policy is used (5 retries with a one-minute delay between attempts).",
             "type" : "object"
           },
           "sealed" : {
@@ -2091,7 +2092,7 @@
             "type" : "boolean"
           },
           "socket-timeout" : {
-            "description" : "Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
+            "description" : "Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
             "example" : 1000,
             "type" : "integer"
           },
@@ -2111,8 +2112,7 @@
         "description" : "BackupRoutine represents a scheduled backup operation routine.",
         "properties" : {
           "backup-policy" : {
-            "description" : "The name of the corresponding backup policy.",
-            "example" : "keepAllPolicy",
+            "description" : "The name of the corresponding backup policy (optional).",
             "type" : "string"
           },
           "bin-list" : {
@@ -2124,7 +2124,7 @@
             "type" : "array"
           },
           "disabled" : {
-            "description" : "Whether this routine is disabled and should not run.",
+            "description" : "Whether this routine is disabled and should not run. Default: false.",
             "type" : "boolean"
           },
           "incr-interval-cron" : {
@@ -2133,7 +2133,7 @@
             "type" : "string"
           },
           "interval-cron" : {
-            "description" : "The interval for full backup as a cron expression string.",
+            "description" : "The interval for full backup as a cron expression string.\nCron expression format: https://github.com/reugn/go-quartz?tab=readme-ov-file#cron-expression-format",
             "example" : "0 0 * * * *",
             "type" : "string"
           },
@@ -2146,20 +2146,18 @@
             "type" : "array"
           },
           "node-list" : {
-            "description" : "NodeList contains a list of nodes to back up.\nBackup the given cluster nodes only.\nIf it is set, ParallelNodes automatically set to true.\nThis argument is mutually exclusive to partition-list/AfterDigest arguments.",
-            "example" : [ "<IP addr 1>:<port 1>[", "<IP addr 2>:<port 2>[", "...]]" ],
+            "description" : "NodeList specifies which Aerospike nodes to include in the backup.\nOnly the listed nodes will be backed up.\nEach node can be specified as one of the following:\n- \"<IP address>:<port>\"\n- \"<hostname>:<port>\"\n- \"<node ID>\"\nTo obtain node identifiers, run: `asinfo -v \"service:\"`.\nIf using IP addresses or hostnames, ensure they match the values returned by the `asinfo` command.\nThis field is mutually exclusive with partition-list.\nParallelism is determined by the number of listed nodes unless `BackupPolicy.Parallel` is set to a lower value.",
             "items" : {
               "type" : "string"
             },
             "type" : "array"
           },
           "partition-list" : {
-            "description" : "Back up list of partition filters. Partition filters can be ranges or individual partitions.\nRange is a pair of partition number and count.\nExample: \"0,100-50\" will backup partitions 0 and 50 partitions starting 100.\nDefault number of partitions to back up: 0 to 4095: all partitions.",
-            "example" : "0-1000",
+            "description" : "PartitionList defines the list of partitions to include in the backup.\nThe format supports individual partitions or ranges.\n- A range is specified as \"<start>,<count>\" (e.g., \"100,50\" backs up 50 partitions starting from 100).\n- A single partition is specified as a number (e.g., \"0\").\nMultiple entries can be comma-separated: e.g., \"0,100,200,300,400,500\".\nBy default, all partitions (0 to 4095) are backed up.\nThis field is mutually exclusive with node-list.",
             "type" : "string"
           },
           "prefer-racks" : {
-            "description" : "A list of Aerospike Server rack IDs to prefer when reading records for a backup.",
+            "description" : "PreferRacks specifies a list of Aerospike Server rack IDs to prioritize when reading records during backup.\nThis is optional and can be used to optimize for rack-aware deployments.",
             "example" : [ 0 ],
             "items" : {
               "type" : "integer"
@@ -2607,12 +2605,12 @@
         "description" : "RestoreNamespace specifies an alternative namespace name for the restore operation.",
         "properties" : {
           "destination" : {
-            "description" : "Destination namespace name.",
+            "description" : "Name of the destination namespace to restore data into.",
             "example" : "destination-ns",
             "type" : "string"
           },
           "source" : {
-            "description" : "Original namespace name.",
+            "description" : "Original namespace name.\nThis field is required as a safeguard to ensure intentional namespace remapping.",
             "example" : "source-ns",
             "type" : "string"
           }
@@ -2629,7 +2627,7 @@
             "type" : "integer"
           },
           "batch-size" : {
-            "description" : "The max allowed number of records per an async batch write call.\nDefault is 128 with batch writes enabled, or 16 without batch writes.",
+            "description" : "The max allowed number of records per an async batch write call.\nOnly applicable when using batch writes.\nDefault: 128.",
             "example" : 128,
             "type" : "integer"
           },
@@ -2645,7 +2643,7 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.CompressionPolicy"
             } ],
-            "description" : "Compression details.",
+            "description" : "Compression details (algorithm). Default is no compression.",
             "type" : "object"
           },
           "disable-batch-writes" : {
@@ -2656,7 +2654,7 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.EncryptionPolicy"
             } ],
-            "description" : "Encryption details.",
+            "description" : "Encryption details (algorithm and key). Default is no encryption.",
             "type" : "object"
           },
           "extra-ttl" : {
@@ -2673,7 +2671,7 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.RestoreNamespace"
             } ],
-            "description" : "Namespace details for the restore operation.\nBy default, the data is restored to the namespace from which it was taken.",
+            "description" : "Namespace optionally specifies an alternative namespace name for the restore operation.\nBy default, the data is restored to the namespace from which it was taken.",
             "type" : "object"
           },
           "no-generation" : {
@@ -2685,7 +2683,7 @@
             "type" : "boolean"
           },
           "no-records" : {
-            "description" : "Do not restore any record data (metadata or bin data).\nBy default, record data, secondary index definitions, and UDF modules\nwill be restored.",
+            "description" : "Do not restore any record data (metadata or bin data).\nBy default, record data, secondary index definitions, and UDF modules will be restored.",
             "type" : "boolean"
           },
           "no-udfs" : {
@@ -2693,7 +2691,7 @@
             "type" : "boolean"
           },
           "parallel" : {
-            "description" : "The number of concurrent record readers from backup files.",
+            "description" : "The number of concurrent record readers from backup files.\nThis value controls the level of parallelism used by the backup service when\nreading backup files.\nThe optimal value depends on hardware and network configuration.\nDefault: 8.",
             "example" : 8,
             "type" : "integer"
           },
@@ -2705,7 +2703,7 @@
             "allOf" : [ {
               "$ref" : "#/components/schemas/dto.RetryPolicy"
             } ],
-            "description" : "Configuration of retries for each restore write operation.\nIf nil, default retry policy will be used.",
+            "description" : "Configuration of retries for each restore write operation.\nIf nil, the default policy is used (5 retries with a one-minute delay between attempts).",
             "type" : "object"
           },
           "set-list" : {
@@ -2717,7 +2715,7 @@
             "type" : "array"
           },
           "socket-timeout" : {
-            "description" : "Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.\nSocket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
+            "description" : "Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.\nSocket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.\nIf both are 0, there is no socket idle time limit.",
             "example" : 1000,
             "type" : "integer"
           },
@@ -3094,6 +3092,8 @@
           "port" : {
             "description" : "The port of the node.",
             "example" : 3000,
+            "maximum" : 65535,
+            "minimum" : 1,
             "type" : "integer"
           },
           "tls-name" : {
diff --git a/docs/openapi.yaml b/docs/openapi.yaml
index b9e204d3b..1e5b56326 100644
--- a/docs/openapi.yaml
+++ b/docs/openapi.yaml
@@ -1277,7 +1277,7 @@ components:
           description: The authentication details to the Aerospike cluster.
           type: object
         label:
-          description: The cluster name.
+          description: "The cluster name. Optional: used only in logs and error messages."
           example: testCluster
           type: string
         max-parallel-scans:
@@ -1298,6 +1298,8 @@ components:
           description: Whether should use "services-alternate" instead of "services"
             in info request during cluster tending.
           type: boolean
+      required:
+      - seed-nodes
       type: object
     dto.AzureStorage:
       properties:
@@ -1476,14 +1478,17 @@ components:
       properties:
         bandwidth:
           description: |-
-            Throttles backup write operations to the backup file(s) to not exceed the given
-            bandwidth in MiB/s.
+            Throttles backup write speed to a maximum of the specified bandwidth in MiB/s.
+            Default is no limit.
           example: 10000
           type: integer
         compression:
           allOf:
           - $ref: '#/components/schemas/dto.CompressionPolicy'
-          description: Compression details.
+          description: |-
+            Compression details (algorithm and mode). Default is no compression.
+            Enabling compression reduces storage and network usage, but increases CPU usage during the backup.
+            Depending on the system configuration, compression may improve or degrade overall performance.
           type: object
         concurrent-incremental:
           description: |-
@@ -1493,12 +1498,12 @@ components:
         encryption:
           allOf:
           - $ref: '#/components/schemas/dto.EncryptionPolicy'
-          description: Encryption details.
+          description: Encryption details (algorithm and key). Default is no encryption.
           type: object
         file-limit:
           description: |-
             File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,
-            a new backup file will be created.
+            a new backup file will be created. Default is 250 MB.
           example: 1024
           type: integer
         no-indexes:
@@ -1512,26 +1517,31 @@ components:
           description: "Do not back up any UDF modules. Default: false."
           type: boolean
         parallel:
-          description: Maximum number of scan calls to run in parallel.
+          description: |-
+            Maximum number of scan calls to run in parallel. Each scan call processes a subset of the total
+            data partitions. The optimal value depends on hardware and network configuration.
+            Default: 8.
           example: 1
           type: integer
         records-per-second:
-          description: |-
-            Limit total returned records per second (RPS). If RPS is zero (the default),
-            the records-per-second limit is not applied.
+          description: Limits the number of records returned per second (RPS). Default
+            is no limit.
           example: 1000
           type: integer
         retention:
           allOf:
           - $ref: '#/components/schemas/dto.RetentionPolicy'
-          description: Specifies how long to retain full and incremental backups.
+          description: |-
+            Specifies how long to retain full and incremental backups.
+            Cleanup runs asynchronously after each successful full backup, never deleting backups preemptively.
+            Ensure storage capacity for at least one extra full backup beyond the retention configuration.
           type: object
         retry-policy:
           allOf:
           - $ref: '#/components/schemas/dto.RetryPolicy'
           description: |-
-            RetryPolicy defines the configuration for retry attempts in case of failures.
-            If nil, default policy is used.
+            RetryPolicy defines the configuration for database scan retry attempts in case of failures.
+            If nil, the default policy is used (5 retries with a one-minute delay between attempts).
           type: object
         sealed:
           description: |-
@@ -1542,7 +1552,7 @@ components:
           type: boolean
         socket-timeout:
           description: |-
-            Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.
+            Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.
             If both are 0, there is no socket idle time limit.
           example: 1000
           type: integer
@@ -1566,22 +1576,20 @@ components:
         set-list:
         - set1
         interval-cron: 0 0 * * * *
-        backup-policy: keepAllPolicy
+        backup-policy: backup-policy
         node-list:
-        - "<IP addr 1>:<port 1>["
-        - "<IP addr 2>:<port 2>["
-        - "...]]"
+        - node-list
+        - node-list
         prefer-racks:
         - 0
         source-cluster: testCluster
         disabled: true
-        partition-list: 0-1000
+        partition-list: partition-list
         namespaces:
         - source-ns1
       properties:
         backup-policy:
-          description: The name of the corresponding backup policy.
-          example: keepAllPolicy
+          description: The name of the corresponding backup policy (optional).
           type: string
         bin-list:
           description: "The list of backup bin names (optional, an empty list implies\
@@ -1592,7 +1600,8 @@ components:
             type: string
           type: array
         disabled:
-          description: Whether this routine is disabled and should not run.
+          description: "Whether this routine is disabled and should not run. Default:\
+            \ false."
           type: boolean
         incr-interval-cron:
           description: The interval for incremental backup as a cron expression string
@@ -1600,7 +1609,9 @@ components:
           example: '*/10 * * * * *'
           type: string
         interval-cron:
-          description: The interval for full backup as a cron expression string.
+          description: |-
+            The interval for full backup as a cron expression string.
+            Cron expression format: https://github.com/reugn/go-quartz?tab=readme-ov-file#cron-expression-format
           example: 0 0 * * * *
           type: string
         namespaces:
@@ -1613,28 +1624,33 @@ components:
           type: array
         node-list:
           description: |-
-            NodeList contains a list of nodes to back up.
-            Backup the given cluster nodes only.
-            If it is set, ParallelNodes automatically set to true.
-            This argument is mutually exclusive to partition-list/AfterDigest arguments.
-          example:
-          - "<IP addr 1>:<port 1>["
-          - "<IP addr 2>:<port 2>["
-          - "...]]"
+            NodeList specifies which Aerospike nodes to include in the backup.
+            Only the listed nodes will be backed up.
+            Each node can be specified as one of the following:
+            - "<IP address>:<port>"
+            - "<hostname>:<port>"
+            - "<node ID>"
+            To obtain node identifiers, run: `asinfo -v "service:"`.
+            If using IP addresses or hostnames, ensure they match the values returned by the `asinfo` command.
+            This field is mutually exclusive with partition-list.
+            Parallelism is determined by the number of listed nodes unless `BackupPolicy.Parallel` is set to a lower value.
           items:
             type: string
           type: array
         partition-list:
           description: |-
-            Back up list of partition filters. Partition filters can be ranges or individual partitions.
-            Range is a pair of partition number and count.
-            Example: "0,100-50" will backup partitions 0 and 50 partitions starting 100.
-            Default number of partitions to back up: 0 to 4095: all partitions.
-          example: 0-1000
+            PartitionList defines the list of partitions to include in the backup.
+            The format supports individual partitions or ranges.
+            - A range is specified as "<start>,<count>" (e.g., "100,50" backs up 50 partitions starting from 100).
+            - A single partition is specified as a number (e.g., "0").
+            Multiple entries can be comma-separated: e.g., "0,100,200,300,400,500".
+            By default, all partitions (0 to 4095) are backed up.
+            This field is mutually exclusive with node-list.
           type: string
         prefer-racks:
-          description: A list of Aerospike Server rack IDs to prefer when reading
-            records for a backup.
+          description: |-
+            PreferRacks specifies a list of Aerospike Server rack IDs to prioritize when reading records during backup.
+            This is optional and can be used to optimize for rack-aware deployments.
           example:
           - 0
           items:
@@ -1762,16 +1778,15 @@ components:
             set-list:
             - set1
             interval-cron: 0 0 * * * *
-            backup-policy: keepAllPolicy
+            backup-policy: backup-policy
             node-list:
-            - "<IP addr 1>:<port 1>["
-            - "<IP addr 2>:<port 2>["
-            - "...]]"
+            - node-list
+            - node-list
             prefer-racks:
             - 0
             source-cluster: testCluster
             disabled: true
-            partition-list: 0-1000
+            partition-list: partition-list
             namespaces:
             - source-ns1
       properties:
@@ -2144,11 +2159,13 @@ components:
         restore operation.
       properties:
         destination:
-          description: Destination namespace name.
+          description: Name of the destination namespace to restore data into.
           example: destination-ns
           type: string
         source:
-          description: Original namespace name.
+          description: |-
+            Original namespace name.
+            This field is required as a safeguard to ensure intentional namespace remapping.
           example: source-ns
           type: string
       required:
@@ -2166,7 +2183,8 @@ components:
         batch-size:
           description: |-
             The max allowed number of records per an async batch write call.
-            Default is 128 with batch writes enabled, or 16 without batch writes.
+            Only applicable when using batch writes.
+            Default: 128.
           example: 128
           type: integer
         bin-list:
@@ -2181,7 +2199,7 @@ components:
         compression:
           allOf:
           - $ref: '#/components/schemas/dto.CompressionPolicy'
-          description: Compression details.
+          description: Compression details (algorithm). Default is no compression.
           type: object
         disable-batch-writes:
           description: |-
@@ -2191,7 +2209,7 @@ components:
         encryption:
           allOf:
           - $ref: '#/components/schemas/dto.EncryptionPolicy'
-          description: Encryption details.
+          description: Encryption details (algorithm and key). Default is no encryption.
           type: object
         extra-ttl:
           description: |-
@@ -2208,7 +2226,7 @@ components:
           allOf:
           - $ref: '#/components/schemas/dto.RestoreNamespace'
           description: |-
-            Namespace details for the restore operation.
+            Namespace optionally specifies an alternative namespace name for the restore operation.
             By default, the data is restored to the namespace from which it was taken.
           type: object
         no-generation:
@@ -2223,14 +2241,18 @@ components:
         no-records:
           description: |-
             Do not restore any record data (metadata or bin data).
-            By default, record data, secondary index definitions, and UDF modules
-            will be restored.
+            By default, record data, secondary index definitions, and UDF modules will be restored.
           type: boolean
         no-udfs:
           description: Do not restore any UDF modules.
           type: boolean
         parallel:
-          description: The number of concurrent record readers from backup files.
+          description: |-
+            The number of concurrent record readers from backup files.
+            This value controls the level of parallelism used by the backup service when
+            reading backup files.
+            The optimal value depends on hardware and network configuration.
+            Default: 8.
           example: 8
           type: integer
         replace:
@@ -2244,7 +2266,7 @@ components:
           - $ref: '#/components/schemas/dto.RetryPolicy'
           description: |-
             Configuration of retries for each restore write operation.
-            If nil, default retry policy will be used.
+            If nil, the default policy is used (5 retries with a one-minute delay between attempts).
           type: object
         set-list:
           description: "The sets to restore (optional, an empty list implies restoring\
@@ -2258,7 +2280,7 @@ components:
         socket-timeout:
           description: |-
             Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.
-            Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.
+            Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.
             If both are 0, there is no socket idle time limit.
           example: 1000
           type: integer
@@ -2645,6 +2667,8 @@ components:
         port:
           description: The port of the node.
           example: 3000
+          maximum: 65535
+          minimum: 1
           type: integer
         tls-name:
           description: TLS certificate name used for secure connections (if enabled).
diff --git a/pkg/dto/aerospike_cluster.go b/pkg/dto/aerospike_cluster.go
index edf3e82fc..ec98ccb4b 100644
--- a/pkg/dto/aerospike_cluster.go
+++ b/pkg/dto/aerospike_cluster.go
@@ -14,10 +14,10 @@ import (
 // AerospikeCluster represents the configuration for an Aerospike cluster for backup.
 // @Description AerospikeCluster represents the configuration for an Aerospike cluster for backup.
 type AerospikeCluster struct {
-	// The cluster name.
+	// The cluster name. Optional: used only in logs and error messages.
 	ClusterLabel *string `yaml:"label,omitempty" json:"label,omitempty" example:"testCluster"`
 	// The seed nodes details.
-	SeedNodes []SeedNode `yaml:"seed-nodes,omitempty" json:"seed-nodes,omitempty"`
+	SeedNodes []SeedNode `yaml:"seed-nodes,omitempty" json:"seed-nodes,omitempty" validate:"required"`
 	// The connection timeout in milliseconds.
 	ConnTimeout *int64 `yaml:"conn-timeout,omitempty" json:"conn-timeout,omitempty" example:"5000"`
 	// Whether should use "services-alternate" instead of "services" in info request during cluster tending.
@@ -27,7 +27,7 @@ type AerospikeCluster struct {
 	// The cluster TLS configuration.
 	TLS *TLS `yaml:"tls,omitempty" json:"tls,omitempty"`
 	// Specifies the maximum number of parallel scans per the cluster.
-	MaxParallelScans *int `yaml:"max-parallel-scans,omitempty" json:"max-parallel-scans,omitempty" example:"100" validate:"optional"`
+	MaxParallelScans *int `yaml:"max-parallel-scans,omitempty" json:"max-parallel-scans,omitempty" example:"100"`
 }
 
 // Validate validates the Aerospike cluster entity.
@@ -242,9 +242,9 @@ type SeedNode struct {
 	// The host name of the node.
 	HostName string `yaml:"host-name,omitempty" json:"host-name,omitempty" example:"localhost" validate:"required"`
 	// The port of the node.
-	Port Port `yaml:"port,omitempty" json:"port,omitempty" example:"3000" validate:"required"`
+	Port Port `yaml:"port,omitempty" json:"port,omitempty" example:"3000" validate:"required,min=1,max=65535"`
 	// TLS certificate name used for secure connections (if enabled).
-	TLSName string `yaml:"tls-name,omitempty" json:"tls-name,omitempty" example:"certName" validate:"optional"`
+	TLSName string `yaml:"tls-name,omitempty" json:"tls-name,omitempty" example:"certName"`
 }
 
 // Validate validates the SeedNode entity.
diff --git a/pkg/dto/backup_policy.go b/pkg/dto/backup_policy.go
index 6e37acbcd..0a7fe25dd 100644
--- a/pkg/dto/backup_policy.go
+++ b/pkg/dto/backup_policy.go
@@ -12,17 +12,21 @@ import (
 // BackupPolicy represents a scheduled backup policy.
 // @Description BackupPolicy represents a scheduled backup policy.
 type BackupPolicy struct {
-	// Maximum number of scan calls to run in parallel.
+	// Maximum number of scan calls to run in parallel. Each scan call processes a subset of the total
+	// data partitions. The optimal value depends on hardware and network configuration.
+	// Default: 8.
 	Parallel *int `yaml:"parallel,omitempty" json:"parallel,omitempty" example:"1"`
-	// Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.
+	// Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.
 	// If both are 0, there is no socket idle time limit.
 	SocketTimeout *int64 `yaml:"socket-timeout,omitempty" json:"socket-timeout,omitempty" example:"1000"`
 	// Total socket timeout in milliseconds. Default is 0, that is, no timeout.
 	TotalTimeout *int64 `yaml:"total-timeout,omitempty" json:"total-timeout,omitempty" example:"2000"`
-	// RetryPolicy defines the configuration for retry attempts in case of failures.
-	// If nil, default policy is used.
+	// RetryPolicy defines the configuration for database scan retry attempts in case of failures.
+	// If nil, the default policy is used (5 retries with a one-minute delay between attempts).
 	RetryPolicy *RetryPolicy `yaml:"retry-policy,omitempty" json:"retry-policy,omitempty"`
 	// Specifies how long to retain full and incremental backups.
+	// Cleanup runs asynchronously after each successful full backup, never deleting backups preemptively.
+	// Ensure storage capacity for at least one extra full backup beyond the retention configuration.
 	RetentionPolicy *RetentionPolicy `yaml:"retention,omitempty" json:"retention,omitempty"`
 	// Do not back up any record data (metadata or bin data). Default: false.
 	NoRecords *bool `yaml:"no-records,omitempty" json:"no-records,omitempty"`
@@ -32,18 +36,19 @@ type BackupPolicy struct {
 	NoUdfs *bool `yaml:"no-udfs,omitempty" json:"no-udfs,omitempty"`
 	// Back up Aerospike cluster configuration. Default: false.
 	WithClusterConfig *bool `yaml:"with-cluster-configuration,omitempty" json:"with-cluster-configuration,omitempty"`
-	// Throttles backup write operations to the backup file(s) to not exceed the given
-	// bandwidth in MiB/s.
+	// Throttles backup write speed to a maximum of the specified bandwidth in MiB/s.
+	// Default is no limit.
 	Bandwidth *int `yaml:"bandwidth,omitempty" json:"bandwidth,omitempty" example:"10000"`
-	// Limit total returned records per second (RPS). If RPS is zero (the default),
-	// the records-per-second limit is not applied.
+	// Limits the number of records returned per second (RPS). Default is no limit.
 	RecordsPerSecond *int `yaml:"records-per-second,omitempty" json:"records-per-second,omitempty" example:"1000"`
 	// File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,
-	// a new backup file will be created.
+	// a new backup file will be created. Default is 250 MB.
 	FileLimit *int `yaml:"file-limit,omitempty" json:"file-limit,omitempty" example:"1024"`
-	// Encryption details.
+	// Encryption details (algorithm and key). Default is no encryption.
 	EncryptionPolicy *EncryptionPolicy `yaml:"encryption,omitempty" json:"encryption,omitempty"`
-	// Compression details.
+	// Compression details (algorithm and mode). Default is no compression.
+	// Enabling compression reduces storage and network usage, but increases CPU usage during the backup.
+	// Depending on the system configuration, compression may improve or degrade overall performance.
 	CompressionPolicy *CompressionPolicy `yaml:"compression,omitempty" json:"compression,omitempty"`
 	// Sealed determines whether backup should include keys updated during the backup process.
 	// When true, the backup contains only records that last modified before backup started.
@@ -55,7 +60,7 @@ type BackupPolicy struct {
 
 	// Allows incremental backups to run concurrently.
 	// When false (default), incremental backups are skipped if another backup for same routine is in progress.
-	ConcurrentIncremental *bool `yaml:"concurrent-incremental,omitempty" json:"concurrent-incremental,omitempty"` //nolint:lll
+	ConcurrentIncremental *bool `yaml:"concurrent-incremental,omitempty" json:"concurrent-incremental,omitempty"`
 }
 
 // NewBackupPolicyFromReader creates a new BackupPolicy object from a given reader.
diff --git a/pkg/dto/backup_routine.go b/pkg/dto/backup_routine.go
index 0b8b4bbc0..9458ba604 100644
--- a/pkg/dto/backup_routine.go
+++ b/pkg/dto/backup_routine.go
@@ -18,8 +18,8 @@ import (
 //
 //nolint:lll
 type BackupRoutine struct {
-	// The name of the corresponding backup policy.
-	BackupPolicy string `yaml:"backup-policy,omitempty" json:"backup-policy,omitempty" example:"keepAllPolicy"`
+	// The name of the corresponding backup policy (optional).
+	BackupPolicy string `yaml:"backup-policy,omitempty" json:"backup-policy,omitempty"`
 	// The name of the corresponding source cluster.
 	SourceCluster string `yaml:"source-cluster,omitempty" json:"source-cluster,omitempty" example:"testCluster" validate:"required"`
 	// The name of the corresponding storage provider configuration.
@@ -27,6 +27,7 @@ type BackupRoutine struct {
 	// The Secret Agent configuration for the routine (optional).
 	SecretAgent *string `yaml:"secret-agent,omitempty" json:"secret-agent,omitempty" example:"sa"`
 	// The interval for full backup as a cron expression string.
+	// Cron expression format: https://github.com/reugn/go-quartz?tab=readme-ov-file#cron-expression-format
 	IntervalCron string `yaml:"interval-cron" json:"interval-cron" example:"0 0 * * * *" validate:"required"`
 	// The interval for incremental backup as a cron expression string (optional).
 	IncrIntervalCron string `yaml:"incr-interval-cron,omitempty" json:"incr-interval-cron,omitempty" example:"*/10 * * * * *"`
@@ -36,19 +37,32 @@ type BackupRoutine struct {
 	SetList []string `yaml:"set-list,omitempty" json:"set-list,omitempty" example:"set1"`
 	// The list of backup bin names (optional, an empty list implies backing up all bins).
 	BinList []string `yaml:"bin-list,omitempty" json:"bin-list,omitempty" example:"dataBin"`
-	// A list of Aerospike Server rack IDs to prefer when reading records for a backup.
+	// PreferRacks specifies a list of Aerospike Server rack IDs to prioritize when reading records during backup.
+	// This is optional and can be used to optimize for rack-aware deployments.
 	PreferRacks []int `yaml:"prefer-racks,omitempty" json:"prefer-racks,omitempty" example:"0"`
-	// Back up list of partition filters. Partition filters can be ranges or individual partitions.
-	// Range is a pair of partition number and count.
-	// Example: "0,100-50" will backup partitions 0 and 50 partitions starting 100.
-	// Default number of partitions to back up: 0 to 4095: all partitions.
-	PartitionList string `yaml:"partition-list,omitempty" json:"partition-list,omitempty" example:"0-1000"`
-	// NodeList contains a list of nodes to back up.
-	// Backup the given cluster nodes only.
-	// If it is set, ParallelNodes automatically set to true.
-	// This argument is mutually exclusive to partition-list/AfterDigest arguments.
-	NodeList []string `yaml:"node-list,omitempty" json:"node-list,omitempty" example:"<IP addr 1>:<port 1>[,<IP addr 2>:<port 2>[,...]]"`
-	// Whether this routine is disabled and should not run.
+
+	// PartitionList defines the list of partitions to include in the backup.
+	// The format supports individual partitions or ranges.
+	// - A range is specified as "<start>,<count>" (e.g., "100,50" backs up 50 partitions starting from 100).
+	// - A single partition is specified as a number (e.g., "0").
+	// Multiple entries can be comma-separated: e.g., "0,100,200,300,400,500".
+	// By default, all partitions (0 to 4095) are backed up.
+	// This field is mutually exclusive with node-list.
+	PartitionList string `yaml:"partition-list,omitempty" json:"partition-list,omitempty"`
+
+	// NodeList specifies which Aerospike nodes to include in the backup.
+	// Only the listed nodes will be backed up.
+	// Each node can be specified as one of the following:
+	// - "<IP address>:<port>"
+	// - "<hostname>:<port>"
+	// - "<node ID>"
+	// To obtain node identifiers, run: `asinfo -v "service:"`.
+	// If using IP addresses or hostnames, ensure they match the values returned by the `asinfo` command.
+	// This field is mutually exclusive with partition-list.
+	// Parallelism is determined by the number of listed nodes unless `BackupPolicy.Parallel` is set to a lower value.
+	NodeList []string `yaml:"node-list,omitempty" json:"node-list,omitempty"`
+
+	// Whether this routine is disabled and should not run. Default: false.
 	Disabled bool `json:"disabled,omitempty" yaml:"disabled,omitempty"`
 }
 
diff --git a/pkg/dto/config.go b/pkg/dto/config.go
index 9fd90cc4a..a202c6039 100644
--- a/pkg/dto/config.go
+++ b/pkg/dto/config.go
@@ -11,10 +11,9 @@ import (
 
 // Config represents the service configuration file.
 // @Description Config represents the service configuration file.
-//
-//nolint:lll
 type Config struct {
-	ServiceConfig     BackupServiceConfig          `yaml:"service,omitempty" json:"service,omitempty"`
+	ServiceConfig BackupServiceConfig `yaml:"service,omitempty" json:"service,omitempty"`
+	//nolint:lll
 	AerospikeClusters map[string]*AerospikeCluster `yaml:"aerospike-clusters,omitempty" json:"aerospike-clusters,omitempty"`
 	Storage           map[string]*Storage          `yaml:"storage,omitempty" json:"storage,omitempty"`
 	BackupPolicies    map[string]*BackupPolicy     `yaml:"backup-policies,omitempty" json:"backup-policies,omitempty"`
diff --git a/pkg/dto/restore_namespace.go b/pkg/dto/restore_namespace.go
index 8fc815206..3f381ad0e 100644
--- a/pkg/dto/restore_namespace.go
+++ b/pkg/dto/restore_namespace.go
@@ -11,8 +11,9 @@ import (
 // @Description RestoreNamespace specifies an alternative namespace name for the restore operation.
 type RestoreNamespace struct {
 	// Original namespace name.
+	// This field is required as a safeguard to ensure intentional namespace remapping.
 	Source *string `json:"source,omitempty" example:"source-ns" validate:"required"`
-	// Destination namespace name.
+	// Name of the destination namespace to restore data into.
 	Destination *string `json:"destination,omitempty" example:"destination-ns" validate:"required"`
 }
 
diff --git a/pkg/dto/restore_policy.go b/pkg/dto/restore_policy.go
index 79392e568..d6421b5e4 100644
--- a/pkg/dto/restore_policy.go
+++ b/pkg/dto/restore_policy.go
@@ -10,17 +10,20 @@ import (
 // @Description RestorePolicy represents a policy for the restore operation.
 type RestorePolicy struct {
 	// The number of concurrent record readers from backup files.
+	// This value controls the level of parallelism used by the backup service when
+	// reading backup files.
+	// The optimal value depends on hardware and network configuration.
+	// Default: 8.
 	Parallel *int `json:"parallel,omitempty" example:"8"`
 	// Do not restore any record data (metadata or bin data).
-	// By default, record data, secondary index definitions, and UDF modules
-	// will be restored.
+	// By default, record data, secondary index definitions, and UDF modules will be restored.
 	NoRecords *bool `json:"no-records,omitempty"`
 	// Do not restore any secondary index definitions.
 	NoIndexes *bool `json:"no-indexes,omitempty"`
 	// Do not restore any UDF modules.
 	NoUdfs *bool `json:"no-udfs,omitempty"`
 	// Timeout (ms) for Aerospike commands to write records, create indexes and create UDFs.
-	// Socket timeout in milliseconds. Default is 10 seconds. If this value is 0, it is set to total-timeout.
+	// Socket timeout in milliseconds. Default is 10 minutes. If this value is 0, it is set to total-timeout.
 	// If both are 0, there is no socket idle time limit.
 	SocketTimeout *int64 `yaml:"socket-timeout,omitempty" json:"socket-timeout,omitempty" example:"1000"`
 	// Total socket timeout in milliseconds. Default is 0, that is, no timeout.
@@ -31,9 +34,10 @@ type RestorePolicy struct {
 	// The max number of outstanding async record batch write calls at a time.
 	MaxAsyncBatches *int `json:"max-async-batches,omitempty" example:"32"`
 	// The max allowed number of records per an async batch write call.
-	// Default is 128 with batch writes enabled, or 16 without batch writes.
+	// Only applicable when using batch writes.
+	// Default: 128.
 	BatchSize *int `json:"batch-size,omitempty" example:"128"`
-	// Namespace details for the restore operation.
+	// Namespace optionally specifies an alternative namespace name for the restore operation.
 	// By default, the data is restored to the namespace from which it was taken.
 	Namespace *RestoreNamespace `json:"namespace,omitempty"`
 	// The sets to restore (optional, an empty list implies restoring all sets).
@@ -57,12 +61,12 @@ type RestorePolicy struct {
 	// Throttles read operations from the backup file(s) to not exceed the given number of transactions
 	// per second.
 	Tps *int `json:"tps,omitempty" example:"4000"`
-	// Encryption details.
+	// Encryption details (algorithm and key). Default is no encryption.
 	EncryptionPolicy *EncryptionPolicy `yaml:"encryption,omitempty" json:"encryption,omitempty"`
-	// Compression details.
+	// Compression details (algorithm). Default is no compression.
 	CompressionPolicy *CompressionPolicy `yaml:"compression,omitempty" json:"compression,omitempty"`
 	// Configuration of retries for each restore write operation.
-	// If nil, default retry policy will be used.
+	// If nil, the default policy is used (5 retries with a one-minute delay between attempts).
 	RetryPolicy *RetryPolicy `yaml:"retry-policy,omitempty" json:"retry-policy,omitempty"`
 	// Amount of extra time-to-live to add to records that have expirable void-times.
 	// Must be set in seconds.
diff --git a/pkg/dto/restore_request.go b/pkg/dto/restore_request.go
index b58003c39..1d3f44476 100644
--- a/pkg/dto/restore_request.go
+++ b/pkg/dto/restore_request.go
@@ -39,7 +39,7 @@ type RestoreTimestampRequest struct {
 	*SecretAgentConfig
 	StorageConfig
 	// Restore policy to use in the operation.
-	Policy *RestorePolicy `json:"policy"`
+	Policy *RestorePolicy `json:"policy,omitempty"`
 	// Required epoch time for recovery. The closest backup before the timestamp will be applied.
 	Time int64 `json:"time" format:"int64" example:"1739538000000" validate:"required"`
 	// The backup routine name.


Reviews:
user: login: reugn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T10:13:07Z
user: login: reugn
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-15T13:47:56Z

Review comments:
diff_hunk: @@ -57,12 +60,12 @@ type RestorePolicy struct {
 	// Throttles read operations from the backup file(s) to not exceed the given number of transactions
 	// per second.
 	Tps *int `json:"tps,omitempty" example:"4000"`
-	// Encryption details.
+	// Encryption details (algorithm and key). Default is not encryption.
path: pkg/dto/restore_policy.go
user: login: reugn
body: ```suggestion
	// Encryption details (algorithm and key). Default is no encryption.
```
created_at: 2025-05-15T09:55:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -10,17 +10,19 @@ import (
 // @Description RestorePolicy represents a policy for the restore operation.
 type RestorePolicy struct {
 	// The number of concurrent record readers from backup files.
+	// This value determines the number of threads the backup service will use.
path: pkg/dto/restore_policy.go
user: login: reugn
body: ```suggestion
	// This value controls the level of parallelism used by the backup service when
        // reading backup files.
```
Threads term is not really applicable in this context.
created_at: 2025-05-15T09:59:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,18 +36,19 @@ type BackupPolicy struct {
 	NoUdfs *bool `yaml:"no-udfs,omitempty" json:"no-udfs,omitempty"`
 	// Back up Aerospike cluster configuration. Default: false.
 	WithClusterConfig *bool `yaml:"with-cluster-configuration,omitempty" json:"with-cluster-configuration,omitempty"`
-	// Throttles backup write operations to the backup file(s) to not exceed the given
-	// bandwidth in MiB/s.
+	// Throttles backup write speed to a maximum of the specified bandwidth in MiB/s.
+	// Default is no limit.
 	Bandwidth *int `yaml:"bandwidth,omitempty" json:"bandwidth,omitempty" example:"10000"`
-	// Limit total returned records per second (RPS). If RPS is zero (the default),
-	// the records-per-second limit is not applied.
+	// Limits the number of records returned per second (RPS). Default is no limit.
 	RecordsPerSecond *int `yaml:"records-per-second,omitempty" json:"records-per-second,omitempty" example:"1000"`
 	// File size limit (in MB) for the backup directory. If an .asb backup file crosses this size threshold,
-	// a new backup file will be created.
+	// a new backup file will be created. Default is 250 MB.
 	FileLimit *int `yaml:"file-limit,omitempty" json:"file-limit,omitempty" example:"1024"`
-	// Encryption details.
+	// Encryption details (algorithm and key). Default is not encryption.
path: pkg/dto/backup_policy.go
user: login: reugn
body: ```suggestion
	// Encryption details (algorithm and key). Default is no encryption.
```
created_at: 2025-05-15T10:00:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -12,17 +12,21 @@ import (
 // BackupPolicy represents a scheduled backup policy.
 // @Description BackupPolicy represents a scheduled backup policy.
 type BackupPolicy struct {
-	// Maximum number of scan calls to run in parallel.
+	// Maximum number of scan calls to run in parallel. This value determines the number of threads
+	// the backup service will use. The optimal value depends on hardware and network configuration.
path: pkg/dto/backup_policy.go
user: login: reugn
body: ```suggestion
	// Maximum number of scan calls to run in parallel. Each scan call processes a subset of the total
	// data partitions. The optimal value depends on hardware and network configuration.
```
created_at: 2025-05-15T10:05:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,30 +1,44 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/aerospike/aerospike-backup-service/refs/tags/v3.1.0/docs/config.schema.json
 ---
-# This is sample config
 aerospike-clusters:
-  cluster:
-    use-services-alternate: false
+  abs-cluster: # <--- Custom cluster name
     seed-nodes:
-      - host-name: "127.0.0.1"
+      - host-name: "localhost"
         port: 3000
     credentials:
-      user: "admin"
-      password: "admin"
+      user: "tester"
+      password: "secret:asbackup:psw" # Password will be fetched from the secret agent
+      secret-agent-name: secret-agent  # <--- Refers to secret-agents
+
+secret-agents:
+  secret-agent: # <--- Custom secret agent name
+    address: localhost
+    port: 5000
+    connection-type: tcp
 
 storage:
-  local:
-    local-storage:
-      path: "/var/lib/aerospike-backup-service"
+  s3: # <--- Custom storage name
+    s3-storage: # Storage type; can be one of "local-storage", "s3-storage", "azure-storage", "gcp-storage"
+      path: backups
+      bucket: as-backup-bucket
+      s3-region: eu-central-1
+      min-part-size: 50_000_000 # Upload chunk size in bytes (May affect performance)
 
 backup-policies:
-  policy:
-    parallel: 1
-
+  dailyBackupPolicy: # <--- Custom policy name
+    parallel: 8 # Parallelism level (May affect performance)
+    file-limit: 1000 # Max backup file size in MB (May affect performance)
+    compression: # Backup files will be compressed before uploading (May affect performance)
+      mode: ZSTD
+      level: 1
+    retention:
+      full: 10 # Retain 10 full backups
+      incremental: 5 # Retain incremental backups for the 5 latest full backups
 
 backup-routines:
-  routine:
-    interval-cron: "1/30 * * * * *" # every 30 seconds
-    incr-interval-cron: "1/5 * * * * *" # every 5 seconds
-    backup-policy: "policy"
-    source-cluster: "cluster"
-    storage: "local"
-    namespace: "test"
+  dailyLocalBackupRoutine: # <--- Custom routine name
+    interval-cron: "@daily" # Full backup will be triggered daily at midnight
+    incr-interval-cron: "0 */2 * * * *" # Incremental backups every 2 hours
+    source-cluster: abs-cluster         # <--- Refers to aerospike-clusters
+    storage: s3                         # <--- Refers to storage
+    backup-policy: dailyBackupPolicy    # <--- Refers to backup-policies
path: build/package/config/aerospike-backup-service.yml
user: login: reugn
body: ```suggestion
    source-cluster: abs-cluster         # <--- Refers to the cluster name under aerospike-clusters
    storage: s3                         # <--- Refers to the storage name under storage
    backup-policy: dailyBackupPolicy    # <--- Refers to the policy name under backup-policies
```
created_at: 2025-05-15T10:12:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,30 +1,44 @@
+# yaml-language-server: $schema=https://raw.githubusercontent.com/aerospike/aerospike-backup-service/refs/tags/v3.1.0/docs/config.schema.json
 ---
-# This is sample config
 aerospike-clusters:
-  cluster:
-    use-services-alternate: false
+  abs-cluster: # <--- Custom cluster name
     seed-nodes:
-      - host-name: "127.0.0.1"
+      - host-name: "localhost"
         port: 3000
     credentials:
-      user: "admin"
-      password: "admin"
+      user: "tester"
+      password: "secret:asbackup:psw" # Password will be fetched from the secret agent
+      secret-agent-name: secret-agent  # <--- Refers to secret-agents
path: build/package/config/aerospike-backup-service.yml
user: login: reugn
body: ```suggestion
      secret-agent-name: secret-agent  # <--- Refers to the secret agent name under secret-agents
```
created_at: 2025-05-15T10:12:45Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov-commenter
created_at: 2025-05-12T11:13:19Z
body: ## [Codecov](https://app.codecov.io/gh/aerospike/aerospike-backup-service/pull/356?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike) Report
:x: Patch coverage is `0%` with `23 lines` in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 49.08%. Comparing base ([`cf93b9c`](https://app.codecov.io/gh/aerospike/aerospike-backup-service/commit/cf93b9c79ac61c08f9ccf16b3a82275b6eabbbc8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike)) to head ([`bac106d`](https://app.codecov.io/gh/aerospike/aerospike-backup-service/commit/bac106d4bf7fffb0260a9c0f42fbcb4e5a4e9273?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike)).
:warning: Report is 150 commits behind head on v3.

| [Files with missing lines](https://app.codecov.io/gh/aerospike/aerospike-backup-service/pull/356?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike) | Patch % | Lines |
|---|---|---|
| [build/readme/readme\_example\_generator.go](https://app.codecov.io/gh/aerospike/aerospike-backup-service/pull/356?src=pr&el=tree&filepath=build%2Freadme%2Freadme_example_generator.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike#diff-YnVpbGQvcmVhZG1lL3JlYWRtZV9leGFtcGxlX2dlbmVyYXRvci5nbw==) | 0.00% | [23 Missing :warning: ](https://app.codecov.io/gh/aerospike/aerospike-backup-service/pull/356?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike) |

<details><summary>Additional details and impacted files</summary>



```diff
@@            Coverage Diff             @@
##               v3     #356      +/-   ##
==========================================
- Coverage   49.22%   49.08%   -0.15%     
==========================================
  Files          72       72              
  Lines        4337     4350      +13     
==========================================
  Hits         2135     2135              
- Misses       2032     2045      +13     
  Partials      170      170              
```
</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/aerospike/aerospike-backup-service/pull/356?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aerospike).
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: korotkov-aerospike
created_at: 2025-05-12T11:17:58Z
body: This PR covers documentation.
I will address logs and error messages separtely.
author_association: CONTRIBUTOR