Repository: benbjohnson/litestream

Issue:
Grafana dashboard
Ciao!

I am trying this project and I just discovered that it exposes some (Prometheus) metrics. So I looked at the repo to find a Grafana dashboard but I didn't found any.

I jumped into the task of creating one (simple):

![Captura de pantalla 2021-02-26 a las 10 12 04](https://user-images.githubusercontent.com/14357604/109280724-aef9f900-781b-11eb-87cb-84bd5cb4a576.png)

I'm sure it can be improved, but if you consider it is a good starting point, I can share it with you with a PR.

Thanks!

Hints from issue comments:
@benbjohnson: Thanks, @angelbarrera92. That's looking like a good start. I have a dashboard on InfluxDB that I can port over to Grafana.@angelbarrera92: leaving the dashboard here just in case: https://gist.github.com/angelbarrera92/3fd1782776150a82ba6f39b5b3d2ccec
Thanks!

Solution patch:
diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml
index 9827031..e2c8286 100644
--- a/.github/workflows/commit.yml
+++ b/.github/workflows/commit.yml
@@ -294,3 +294,55 @@ jobs:
           LITESTREAM_SFTP_USER:     "root"
           LITESTREAM_SFTP_KEY_PATH: /test/id_ed25519
           LITESTREAM_SFTP_PATH:     /test/data
+
+      - name: Test SFTP with concurrent writes enabled (default)
+        run: |
+          cat > /tmp/sftp-concurrent.yml <<EOF
+          dbs:
+            - path: /tmp/test-concurrent.db
+              replicas:
+                - type: sftp
+                  host: localhost:2222
+                  key-path: /test/id_ed25519
+                  user: root
+                  path: /test/data/concurrent
+                  concurrent-writes: true
+          EOF
+
+          # Create test database
+          sqlite3 /tmp/test-concurrent.db <<SQL
+          CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT);
+          INSERT INTO test (data) VALUES ('test1'), ('test2'), ('test3');
+          SQL
+
+          # Run replication briefly
+          timeout 5 ./bin/litestream replicate -config /tmp/sftp-concurrent.yml || true
+
+          # Check files were created
+          ssh -i /test/id_ed25519 -o StrictHostKeyChecking=accept-new -p 2222 root@localhost "ls -la /test/data/concurrent/" || true
+
+      - name: Test SFTP with concurrent writes disabled
+        run: |
+          cat > /tmp/sftp-sequential.yml <<EOF
+          dbs:
+            - path: /tmp/test-sequential.db
+              replicas:
+                - type: sftp
+                  host: localhost:2222
+                  key-path: /test/id_ed25519
+                  user: root
+                  path: /test/data/sequential
+                  concurrent-writes: false
+          EOF
+
+          # Create test database
+          sqlite3 /tmp/test-sequential.db <<SQL
+          CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT);
+          INSERT INTO test (data) VALUES ('test1'), ('test2'), ('test3');
+          SQL
+
+          # Run replication briefly
+          timeout 5 ./bin/litestream replicate -config /tmp/sftp-sequential.yml || true
+
+          # Check files were created
+          ssh -i /test/id_ed25519 -o StrictHostKeyChecking=accept-new -p 2222 root@localhost "ls -la /test/data/sequential/" || true
diff --git a/grafana/README.md b/grafana/README.md
new file mode 100644
index 0000000..fdf8772
--- /dev/null
+++ b/grafana/README.md
@@ -0,0 +1,55 @@
+# Litestream Grafana Dashboard
+
+This directory contains a Grafana dashboard for monitoring Litestream metrics.
+
+## Prerequisites
+
+1. Litestream configured with metrics endpoint enabled in `litestream.yml`:
+
+   ```yaml
+   addr: ":9090"
+   ```
+
+2. Prometheus configured to scrape Litestream metrics:
+
+   ```yaml
+   scrape_configs:
+     - job_name: 'litestream'
+       static_configs:
+         - targets: ['localhost:9090']
+   ```
+
+3. Grafana with Prometheus data source configured
+
+## Installation
+
+1. Open Grafana and navigate to **Dashboards** → **Import**
+2. Upload the `litestream-dashboard.json` file or paste its contents
+3. Select your Prometheus data source
+4. Click **Import**
+
+## Metrics Included
+
+The dashboard monitors the following key metrics:
+
+- **Database & WAL Size**: Current size of the database and Write-Ahead Log
+- **Total WAL Bytes Written**: Cumulative bytes written to shadow WAL
+- **Sync Operations**: Rate of sync operations and any sync errors
+- **Sync Duration**: Time spent syncing shadow WAL
+- **Checkpoint Operations**: Rate of checkpoint operations by mode
+- **Checkpoint Errors**: Any checkpoint errors that occur
+- **Transaction ID**: Current transaction ID for each database
+- **Replica Operations**: Operations performed by replica type (GET/PUT)
+- **Replica Throughput**: Bytes transferred by replica operations
+
+## Configuration
+
+The dashboard uses template variables:
+
+- `datasource`: Select your Prometheus data source
+- `job`: Select the Prometheus job name (defaults to "litestream")
+
+## Support
+
+For issues or improvements to this dashboard, please open an issue at:
+<https://github.com/benbjohnson/litestream/issues>
diff --git a/grafana/litestream-dashboard.json b/grafana/litestream-dashboard.json
new file mode 100644
index 0000000..7622e54
--- /dev/null
+++ b/grafana/litestream-dashboard.json
@@ -0,0 +1,872 @@
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "-- Grafana --",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 0,
+  "id": null,
+  "links": [],
+  "panels": [
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "bytes"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 0
+      },
+      "id": 2,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "litestream_db_size{job=\"$job\"}",
+          "legendFormat": "{{db}} - DB Size",
+          "refId": "A"
+        },
+        {
+          "expr": "litestream_wal_size{job=\"$job\"}",
+          "legendFormat": "{{db}} - WAL Size",
+          "refId": "B"
+        }
+      ],
+      "title": "Database & WAL Size",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "thresholds"
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "bytes"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 0
+      },
+      "id": 10,
+      "options": {
+        "orientation": "auto",
+        "reduceOptions": {
+          "values": false,
+          "calcs": [
+            "lastNotNull"
+          ],
+          "fields": ""
+        },
+        "showThresholdLabels": false,
+        "showThresholdMarkers": true,
+        "text": {}
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "litestream_total_wal_bytes{job=\"$job\"}",
+          "legendFormat": "{{db}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Total WAL Bytes Written",
+      "type": "gauge"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "ops"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 8
+      },
+      "id": 3,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_sync_count{job=\"$job\"}[5m])",
+          "legendFormat": "{{db}} - Sync Rate",
+          "refId": "A"
+        }
+      ],
+      "title": "Sync Operations Rate",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "errors/sec"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 8
+      },
+      "id": 4,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_sync_error_count{job=\"$job\"}[5m])",
+          "legendFormat": "{{db}} - Sync Errors",
+          "refId": "A"
+        }
+      ],
+      "title": "Sync Error Rate",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "s"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 16
+      },
+      "id": 5,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_sync_seconds{job=\"$job\"}[5m])",
+          "legendFormat": "{{db}} - Sync Time",
+          "refId": "A"
+        }
+      ],
+      "title": "Sync Duration",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "ops"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 16
+      },
+      "id": 6,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_checkpoint_count{job=\"$job\"}[5m])",
+          "legendFormat": "{{db}} - {{mode}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Checkpoint Operations Rate",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "errors/sec"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 24
+      },
+      "id": 7,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_checkpoint_error_count{job=\"$job\"}[5m])",
+          "legendFormat": "{{db}} - {{mode}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Checkpoint Error Rate",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "none"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 24
+      },
+      "id": 11,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "litestream_txid{job=\"$job\"}",
+          "legendFormat": "{{db}} - Transaction ID",
+          "refId": "A"
+        }
+      ],
+      "title": "Current Transaction ID",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "ops"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 32
+      },
+      "id": 8,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_replica_operation_total{job=\"$job\"}[5m])",
+          "legendFormat": "{{replica_type}} - {{operation}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Replica Operations Rate",
+      "type": "timeseries"
+    },
+    {
+      "datasource": "${datasource}",
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 10,
+            "gradientMode": "none",
+            "hideFrom": {
+              "tooltip": false,
+              "viz": false,
+              "legend": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "never",
+            "spanNulls": true,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "binBps"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 32
+      },
+      "id": 9,
+      "options": {
+        "legend": {
+          "calcs": [],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "pluginVersion": "8.0.0",
+      "targets": [
+        {
+          "expr": "rate(litestream_replica_operation_bytes{job=\"$job\"}[5m])",
+          "legendFormat": "{{replica_type}} - {{operation}}",
+          "refId": "A"
+        }
+      ],
+      "title": "Replica Throughput",
+      "type": "timeseries"
+    }
+  ],
+  "refresh": "30s",
+  "schemaVersion": 27,
+  "style": "dark",
+  "tags": ["litestream", "sqlite", "replication"],
+  "templating": {
+    "list": [
+      {
+        "current": {
+          "selected": false,
+          "text": "Prometheus",
+          "value": "Prometheus"
+        },
+        "hide": 0,
+        "includeAll": false,
+        "label": "Data Source",
+        "multi": false,
+        "name": "datasource",
+        "options": [],
+        "query": "prometheus",
+        "queryValue": "",
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "type": "datasource"
+      },
+      {
+        "current": {
+          "selected": false,
+          "text": "litestream",
+          "value": "litestream"
+        },
+        "datasource": "${datasource}",
+        "definition": "label_values(litestream_db_size, job)",
+        "hide": 0,
+        "includeAll": false,
+        "label": "Job",
+        "multi": false,
+        "name": "job",
+        "options": [],
+        "query": {
+          "query": "label_values(litestream_db_size, job)",
+          "refId": "StandardVariableQuery"
+        },
+        "refresh": 1,
+        "regex": "",
+        "skipUrlSync": false,
+        "sort": 0,
+        "type": "query"
+      }
+    ]
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {},
+  "timezone": "",
+  "title": "Litestream Monitoring",
+  "uid": "litestream-monitoring",
+  "version": 1
+}
diff --git a/sftp/replica_client.go b/sftp/replica_client.go
index 4bb8f4f..f77cf80 100644
--- a/sftp/replica_client.go
+++ b/sftp/replica_client.go
@@ -42,12 +42,17 @@ type ReplicaClient struct {
 	Path        string
 	KeyPath     string
 	DialTimeout time.Duration
+
+	// ConcurrentWrites enables concurrent writes for better performance.
+	// Note: This makes resuming failed transfers unsafe.
+	ConcurrentWrites bool
 }
 
 // NewReplicaClient returns a new instance of ReplicaClient.
 func NewReplicaClient() *ReplicaClient {
 	return &ReplicaClient{
-		DialTimeout: DefaultDialTimeout,
+		DialTimeout:      DefaultDialTimeout,
+		ConcurrentWrites: true, // Default to true for better performance
 	}
 }
 
@@ -104,7 +109,13 @@ func (c *ReplicaClient) Init(ctx context.Context) (_ *sftp.Client, err error) {
 	}
 
 	// Wrap connection with an SFTP client.
-	if c.sftpClient, err = sftp.NewClient(c.sshClient); err != nil {
+	// Configure options based on client settings
+	opts := []sftp.ClientOption{}
+	if c.ConcurrentWrites {
+		opts = append(opts, sftp.UseConcurrentWrites(true))
+	}
+
+	if c.sftpClient, err = sftp.NewClient(c.sshClient, opts...); err != nil {
 		c.sshClient.Close()
 		c.sshClient = nil
 		return nil, err



Test patch:
diff --git a/cmd/litestream/main.go b/cmd/litestream/main.go
index 0121edf..3bf00b1 100644
--- a/cmd/litestream/main.go
+++ b/cmd/litestream/main.go
@@ -556,10 +556,11 @@ type ReplicaConfig struct {
 	AccountKey  string `yaml:"account-key"`
 
 	// SFTP settings
-	Host     string `yaml:"host"`
-	User     string `yaml:"user"`
-	Password string `yaml:"password"`
-	KeyPath  string `yaml:"key-path"`
+	Host             string `yaml:"host"`
+	User             string `yaml:"user"`
+	Password         string `yaml:"password"`
+	KeyPath          string `yaml:"key-path"`
+	ConcurrentWrites *bool  `yaml:"concurrent-writes"`
 
 	// NATS settings
 	JWT           string         `yaml:"jwt"`
@@ -868,6 +869,12 @@ func newSFTPReplicaClientFromConfig(c *ReplicaConfig, _ *litestream.Replica) (_
 	client.Password = password
 	client.Path = path
 	client.KeyPath = c.KeyPath
+
+	// Set concurrent writes if specified, otherwise use default (true)
+	if c.ConcurrentWrites != nil {
+		client.ConcurrentWrites = *c.ConcurrentWrites
+	}
+
 	return client, nil
 }