A backend for konserve that supports Google Cloud Storage.
Add to your dependencies:
(require '[konserve-gcs.core] ;; Registers the :gcs backend
'[konserve.core :as k])
(def config
{:backend :gcs
:bucket "my-bucket"
:location "US-EAST1"
:store-path "my-store"
:id #uuid "550e8400-e29b-41d4-a716-446655440000"
;; Optional:
:project-id "my-gcp-project"})
(def store (k/create-store config {:sync? true}))
For API usage (assoc-in, get-in, delete-store, etc.), see the konserve documentation.
GCS supports multiple independent stores within the same bucket by using different :store-path values:
;; Store 1
(def store1-config
{:backend :gcs
:bucket "my-bucket"
:location "US-EAST1"
:store-path "store1"
:id #uuid "11111111-1111-1111-1111-111111111111"})
;; Store 2 - same bucket, different path
(def store2-config
{:backend :gcs
:bucket "my-bucket"
:location "US-EAST1"
:store-path "store2"
:id #uuid "22222222-2222-2222-2222-222222222222"})
(def store1 (k/create-store store1-config {:sync? true}))
(def store2 (k/create-store store2-config {:sync? true}))
;; Each store maintains its own isolated namespace within the bucket
konserve-gcs supports optimistic concurrency control using GCS's generation-based conditional writes. This enables safe concurrent updates from multiple machines without distributed locks.
;; Enable optimistic locking with up to 10 retries on conflict
(def config
{:backend :gcs
:bucket "my-bucket"
:location "US-EAST1"
:store-path "my-store"
:id #uuid "550e8400-e29b-41d4-a716-446655440000"
:config {:optimistic-locking-retries 10}})
(def store (k/create-store config {:sync? true}))
;; Now update-in is safe across multiple machines!
;; Each machine can run this concurrently:
(k/update-in store [:counter] (fnil inc 0) {:sync? true})
How it works:
generationMatch precondition with the captured generationThis is particularly useful for:
Note: Without optimistic locking enabled, concurrent update-in calls from different machines may lose updates (last-write-wins). With optimistic locking, all updates are preserved through automatic retry.
Note that you do not need full GCS rights if you manage the bucket outside, i.e.
create it before and delete it after usage from a privileged account. Connection
will otherwise create a bucket and all files created by konserve (with suffix
".ksv", ".ksv.new" or ".ksv.backup") will be deleted by delete-store, but the
bucket needs to be separately deleted.
GCS authentication is handled by the Google Cloud SDK. The recommended approaches are:
gcloud auth application-default loginGOOGLE_APPLICATION_CREDENTIALS environment variable to point to your service account JSON key fileSee Google Cloud Authentication documentation for more details.
For local development and testing, you can use fake-gcs-server:
# Start the emulator
docker-compose up -d
# Run tests
./bin/run-unittests
# Or manually connect to the emulator
(def emulator-config
{:backend :gcs
:bucket "test-bucket"
:location "US-EAST1"
:store-path "test-store"
:project-id "test-project"
:host "http://localhost:4443" ;; Emulator endpoint
:id #uuid "550e8400-e29b-41d4-a716-446655440000"})
Copyright © 2024-2026 Patrick Killean, Christian Weilbach
Licensed under MIT (see LICENSE).
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |