How to use the new Archive feature coming CHT 5.3

CHT 5.3 is coming out soon and one of it’s headline features is the ability to archive documents in CouchDB into another database (medicmedic-archive). In advanced of the release, documentation on the feature has been published. Notably, it calls out:

You submit a list of document IDs to the archive API endpoint.

This means it is up to the administrators of the CHT to source the list of IDs and provide it to the API.

How does the list of IDs get generated? What are some technical steps to generate this list?

Let’s dive in!

@jkuester and I agreed there were two main ways to pull IDs from:

  1. Run a query for all reports older than a certain cut off date, possibly filtering by type.
  2. Find documents that are hidden from offline sync or the server via server side or client side purging.

@jkuester - can you walk us through how to generate a list of IDs then based on these two ideas? I believe for #1 the /api/v2/export/reports API allows for a date range to be passed, as well as query for specific report types, correct?

What about finding purged doc IDs that are safe to archive?

Further - opening this up to the community who might have similar questions! @antony - do you know of anyone who might be interested in this thread? @elijah - same question to you :waving_hand:

Cheers!

While testing this feature to write the upcoming 5.3 release notes, I had some key points I wanted to share!

I started off by creating a local dev instance with docker helper. I then used the easy mode in the test data generator to flood the instance with new data.

Note - there used to be a section here about the importance of clearing your sentinel backlog. This turned out to be inaccurate, so it has been removed and an update was posted below.

I then used the /api/v2/export/reports API to download many report IDs. Specifically I picked an arbitrary start time and then converted it to seconds since the epoch. So Monday, August 24, 2026 at 2:35:15 PM UTC-07:00 DST became 1787607315000. I then looked the query format to use against the API - this forum post covers the topic well. Since I wanted the raw IDs, with out any other data, I cleansed the output with cut and sed like so:

curl -qs -g \
  "https://medic:password@192-168-68-26.local-ip.medicmobile.org:10473/api/v2/export/reports?filters[search]=&filters[date][from]=0&filters[date][to]=1787255664000" | \
  cut -f1 -d, | sed "s/\"//g" > test.IDs.to.archive

Be patient! I found this command can take some time to run - for me it took over an hour. Consider a very narrow query (short date period, specific reports etc) to test with before letting it run.

I wanted to slowly test, so i first cut off 10 IDs from the list: head -n10 test.IDs.to.archive > 10.ids.test.archive and ran this against my dev instance with a curl call:

curl -qs -X POST \
  -H "Content-Type: text/csv" \
  --data-binary @10.ids.test.archive \
  https://medic:password@192-168-68-26.local-ip.medicmobile.org:10473/api/v1/archive | jq .

This immediately returned some JSON:

{
  "jobs": [
    {
      "id": "archive:01a035b8-5477-7aa1-9d08-b3e740df9162",
      "count": 10
    }
  ]
}

As my dev instance was still busy indexing new documents sentinel only runs every 5 minutes, at first I was confused because the archive docs say:

Each archive job writes a log document to the medic-logs database with the same ID as the job.

However, I didn’t see any entries in the medic-logs database. I realized that this can take a bit, possibly many minutes for a busy instance until sentinel runs on its regular interval. It can be helpful to tail the logs of your Sentinel container. For me, I used this call:

docker logs -f cht-sentinel-1 --since 100m 2>&1 | grep -E "Archiving: processing job archive|skipped"

When you see activity here, you can then go to into Fauxton and look at the medic-logs database and look for documents that start with archive::

I also had a watchdog instance running so I could monitor the size of the medic database both for test data generate calls increasing it (see #1) and the archive feature decreasing (see #2):

Once I gained confidence in how the system worked, I uploaded file with thousands of lines to the archiving API and used the above techniques to monitor its progress. I was able to successfully archive over 100,000 reports!

I think the main reason for your delay is that Sentinel runs job schedules every 5 minutes.
The archive log is created when job processing starts, which will be delayed by at most 5 minutes sentinel scheduling timeout. So it’s not about busy instance.

Thanks @diana ! I’ve updated my text above to clarify how it works. Great to clear up my confusion - thanks for the comment!

After some good discussion with @diana about this works, I wanted to update this forum thread with two updates:

  1. The archive queue is different than the sentinel backlog queue. While the sentinel service will be the run to process archiving, archiving will not be blocked by a large sentinel backlog which shows in Watchdog.

  2. The nature of archiving so many documents will incur CouchDB fragmentation as thousands (or more!) of documents are moved about. Fragmentation means extra disk space is used until compaction is run. Anecdotally we’ve seen fragmentation cause about 2.5x disk use. However, the faster and the more you archive, the higher disk will go. Consider going slower to use less disk space (but obviously take longer to archive).

Over to @diana to call out any further details or clarifications :folded_hands: !