
cloudantbackup
The source code for this utility is here https://github.com/glynnbird/cloudantbackup
A backup utility for Cloudant databases.
Installation
You will need to download and install the Go compiler. Clone this repo then:
go build ./cmd/cloudantbackup
Then copy the resultant binary cloudantbackup (or cloudantbackup.exe in Windows systems) into your path.
Configuration
cloudantbackup authenticates with your chosen Cloudant service using environment variables as documented here e.g.
CLOUDANT_URL=https://xxxyyy.cloudantnosqldb.appdomain.cloud
CLOUDANT_APIKEY="my_api_key"
Usage
Supply the name of the database to be backed up and pipe the output to a file:
cloudantbackup --db mydb > mydb.txt
Parameters
--db- the database name to backup (REQUIRED)--parallelism- the number of http requests in flight at any one time (default: 5)--buffer-size- the number of documents fetched with each bulk read request (default: 500)--mode- the backup mode. Eitherfullorshallow. Afullbackup fetches all the revisions of each document, ashallowbackup just fetches the winning revision. (default: full)--log- the filename where the backup log will be stored (not the backup data itself) (optional)--resume- a flag to indicate that a previously incomplete backup should be resumed (--logalso required) (optional)--since- where to start the backup from (default:0- the beginning of time)
e.g.
cloudantbackup --db mydb --parallelism 10 --buffer-size 1000 --mode shallow > mydb.txt
Output
The backup itself is written to stdout. It consists of a header line followed by one line per batch of backed-up documents:
{"name":"@cloudant/couchbackup","version":"1.0.0","mode":"full"}
[{"_id":"a","_rev":"1-123","x":1}...]
A progress log is written to stderr:
025/11/25 11:37:35 saved 500 docs. Total: 500
2025/11/25 11:37:35 saved 500 docs. Total: 1000
2025/11/25 11:37:35 saved 500 docs. Total: 1500
2025/11/25 11:37:35 saved 500 docs. Total: 2000
2025/11/25 11:37:35 saved 500 docs. Total: 2500
2025/11/25 11:37:35 saved 500 docs. Total: 3000
2025/11/25 11:37:35 saved 500 docs. Total: 3500
2025/11/25 11:37:35 saved 500 docs. Total: 4000
2025/11/25 11:37:36 saved 500 docs. Total: 4500
2025/11/25 11:37:36 saved 500 docs. Total: 5000
2025/11/25 11:37:36 saved 500 docs. Total: 5500
2025/11/25 11:37:36 saved 500 docs. Total: 6000
2025/11/25 11:37:36 saved 500 docs. Total: 6500
2025/11/25 11:37:36 saved 500 docs. Total: 7000
2025/11/25 11:37:36 saved 500 docs. Total: 7500
2025/11/25 11:37:36 saved 500 docs. Total: 8000
2025/11/25 11:37:36 saved 500 docs. Total: 8500
2025/11/25 11:37:36 saved 500 docs. Total: 9000
2025/11/25 11:37:36 saved 500 docs. Total: 9500
2025/11/25 11:37:36 saved 500 docs. Total: 10000
2025/11/25 11:37:36 saved 500 docs. Total: 10500
2025/11/25 11:37:36 saved 500 docs. Total: 11000
2025/11/25 11:37:36 saved 500 docs. Total: 11500
2025/11/25 11:37:36 saved 500 docs. Total: 12000
2025/11/25 11:37:36 saved 500 docs. Total: 12500
2025/11/25 11:37:36 saved 500 docs. Total: 13000
2025/11/25 11:37:36 saved 500 docs. Total: 13500
2025/11/25 11:37:36 saved 500 docs. Total: 14000
2025/11/25 11:37:36 saved 500 docs. Total: 14500
2025/11/25 11:37:36 saved 500 docs. Total: 15000
2025/11/25 11:37:36 saved 500 docs. Total: 15500
2025/11/25 11:37:38 saved 500 docs. Total: 16000
2025/11/25 11:37:38 saved 500 docs. Total: 16500
2025/11/25 11:37:38 saved 500 docs. Total: 17000
2025/11/25 11:37:38 saved 500 docs. Total: 17500
2025/11/25 11:37:38 saved 500 docs. Total: 18000
2025/11/25 11:37:38 saved 500 docs. Total: 18500
2025/11/25 11:37:38 saved 500 docs. Total: 19000
2025/11/25 11:37:38 Changes follower complete. 23541 changes
2025/11/25 11:37:38 saved 500 docs. Total: 19500
2025/11/25 11:37:38 saved 500 docs. Total: 20000
2025/11/25 11:37:38 saved 500 docs. Total: 20500
2025/11/25 11:37:38 saved 500 docs. Total: 21000
2025/11/25 11:37:38 saved 500 docs. Total: 21500
2025/11/25 11:37:38 saved 500 docs. Total: 22000
2025/11/25 11:37:38 saved 41 docs. Total: 22041
2025/11/25 11:37:38 saved 500 docs. Total: 22541
2025/11/25 11:37:38 saved 500 docs. Total: 23041
2025/11/25 11:37:38 saved 500 docs. Total: 23541
How does it work?
flowchart TD
CF["Changes Follower\n(changes_follower.go)"]
RM["Resume Loader\n(resume.go)"]
JC[/"jobsChan\n(chan Batch)"/]
W1["fetchDocsWorker 1\n(workers.go)"]
W2["fetchDocsWorker 2\n(workers.go)"]
WN["fetchDocsWorker N\n(workers.go)"]
RC[/"resultsChan\n(chan ResultSet)"/]
SC["statsCollector\n(workers.go)"]
CL["Cloudant API\n(_bulk_get)"]
LF[("LogFile\n(logfile.go)")]
OUT["stdout\n(output.go)"]
CF -->|"Batch (doc IDs)"| JC
RM -->|"Batch (doc IDs)"| JC
JC --> W1
JC --> W2
JC --> WN
W1 <-->|"fetch docs"| CL
W2 <-->|"fetch docs"| CL
WN <-->|"fetch docs"| CL
W1 -->|ResultSet| RC
W2 -->|ResultSet| RC
WN -->|ResultSet| RC
RC --> SC
CF -->|"WriteNewBatch"| LF
RM -->|"WriteNewBatch"| LF
SC -->|"WriteDoneBatch"| LF
SC -->|"WriteResult"| OUT
Backup Execution Flow
When a backup is triggered, the following sequence of function calls occurs:
1. Initialization (backup.go)
New()- Creates a new CloudantBackup instance with default dependencies- Loads configuration via
NewAppConfig()(fromappconfig.go) - Sets up Cloudant SDK client
- Calls
NewWithDeps()to initialize the backup structure
- Loads configuration via
2. Main Execution (backup.go)
Run(ctx)- Main orchestration function- Creates cancellable context for coordinated shutdown
- Calls
loadResumeBatches()to check for resume mode (fromresume.go) - Calls
startWorkers()to launch worker goroutines (fromworkers.go) - Calls
produceBatches()to either resume or start fresh (fromresume.go) - Calls
shutdownWorkers()to clean up (fromworkers.go) - Calls
closeResources()to flush and close files
3. Batch Production (Normal Mode)
produceBatches()(resume.go) - Decides between resume or fresh backupSpoolChangesFeed()(backup.go) - Coordinates changes feed processing- Calls
followChangesFeed()(fromchanges_follower.go) - Logs completion and writes to log file
- Calls
4. Changes Feed Processing (changes_follower.go)
-
followChangesFeed()- Consumes the changes feed- Creates changes follower via
changesFollowerFactory.New() - For each change:
- Calls
queueChange()to buffer document IDs - When buffer is full, calls
dispatchBatchToWorker()
- Calls
- On EOF, flushes remaining buffer via
dispatchBatchToWorker()
- Creates changes follower via
-
queueChange()- Adds document ID to buffer- Calls
dispatchBatchToWorker()when buffer reaches capacity
- Calls
-
dispatchBatchToWorker()- Creates and sends batch to workers- Creates
BatchviaNewBatch()(frombatch.go) - Writes to log file if enabled
- Sends batch to
jobsChanfor worker processing
- Creates
5. Worker Goroutines (workers.go)
Multiple workers run concurrently, each executing:
-
fetchDocsWorker()- Main worker loop- Calls
receiveJob()to get next batch fromjobsChan - Calls
processBatch()to fetch and process documents - Calls
sendResult()to send results toresultsChan
- Calls
-
processBatch()- Processes a single batch- Calls
fetchBulkDocs()to make API call - Calls
extractDocuments()to separate successful docs from errors - Marshals documents to JSON
- Calls
-
fetchBulkDocs()- Makes bulk get API call to Cloudant -
extractDocuments()- Processes bulk get results
6. Results Collection (workers.go)
A single collector goroutine runs:
statsCollector()- Collects and writes results- Writes backup header via
output.WriteHeader()(fromoutput.go) - For each result from
resultsChan:- Writes batch to output via
output.WriteResult() - Updates log file via
logFile.WriteDoneBatch()(fromlogfile.go) - Logs progress to stderr
- Writes batch to output via
- Writes backup header via
7. Resume Mode (resume.go)
If --resume flag is set:
-
loadResumeBatches()- Loads pending batches from log file- Calls
logFile.Load()(fromlogfile.go)
- Calls
-
resumeBatches()- Re-enqueues pending batches- Sends each batch to
jobsChanfor processing
- Sends each batch to
Key Design Patterns
- Producer-Consumer: Changes feed produces batches, workers consume them
- Fan-Out: Multiple workers process batches in parallel
- Fan-In: Single collector aggregates results
- Context Cancellation: Coordinated shutdown on errors or completion
- Buffering: Document IDs are batched before fetching to optimize API calls
Differences from couchbackup
- the goroutines that fetch the batches of documents execute in parallel, allowing the backup to proceed more quickly.
- the environment variables that configure the Cloudant service are those defined by the IBM Go SDK, not those used by couchbackup.
- shallow mode simply fetches winning revisions - it isn’t a paginated “all docs” as in couchbackup.
- no
--attachments - no equivalent of couchrestore