---
name: codeengine-persistentdatastore
title: Working with persistent data stores
description: You can mount an IBM Cloud Object Storage(COS) bucket to your IBM Cloud&reg; Code Engine application or job by using a **persistent data store**. This feature allows your workloads to access the contents of a COS bucket through the local file system by using standard file operations.
last-updated: 2026-07-08
---

> ## Documentation Index
> The table of contents for this documentation set is at https://cloud.ibm.com/docs/codeengine?format=markdown
> The index for all IBM Cloud docs is at: https://cloud.ibm.com/docs/llms.txt
> Use these files to discover more information as needed.

# Working with persistent data stores
{: #persistent-data-store}

You can mount an IBM Cloud Object Storage(COS) bucket to your IBM Cloud&reg; Code Engine application or job by using a **persistent data store**. This feature allows your workloads to access the contents of a COS bucket through the local file system by using standard file operations.

A persistent data store in Code Engine is a reference to an existing data store that Code Engine does not manage. Currently, IBM Cloud Object Storage is the only supported data store type. By creating a reference to your COS bucket, you can mount it directly into your application or job container's file system.

## Before you begin
{: #pds-prereqs-ui}
{: ui}

Before you can work with persistent data stores, ensure that the following prerequisites are met.

- You must have an [IBM Cloud Object Storage instance](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-provision&format=markdown).
- You must create a service credential for your Object Storage instance with [**HMAC credentials**](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-uhc-hmac-credentials-main&format=markdown) enabled. The HMAC credential requires at least the **Writer** service access role to read from and write to the bucket. If you only need read access, choose the **Content Reader** service access role instead.
- You must have a bucket available in your Object Storage instance. For more information, see [Create a new bucket](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-getting-started-cloud-object-storage&format=markdown).
- You must have a [Code Engine project](https://cloud.ibm.com/docs/codeengine?topic=codeengine-manage-project&format=markdown) and it must be selected as the current context.

## Step 1: Create an HMAC secret in Code Engine by using the console
{: #pds-create-secret-ui}
{: ui}

To securely access your COS bucket, Code Engine requires the HMAC credentials that are associated with your Object Storage instance. You store these credentials in a secret within your Code Engine project.

Follow [Creating an HMAC secret from the console](https://cloud.ibm.com/docs/codeengine?topic=codeengine-secret&format=markdown#secret-create-ui-hmac) to create a secret of format `HMAC`.

Provide the corresponding values from your COS service credential when prompted.

## Step 2: Create a persistent data store by using the console
{: #pds-create-datastore-ui}
{: ui}

Now, create the persistent data store resource in Code Engine. This resource acts as a reference to your COS bucket and links it with the HMAC secret that you created.

1. Click the name of your project on the [Code Engine Projects page](https://cloud.ibm.com/codeengine/projects){: external}.
2. From the Components page, click **Persistent data stores**.
3. From the Persistent data stores page, click **Create**.
4. From the Create a persistent data store page, complete the following steps:
    1. Provide a name; for example, `mysecret-hmac`.
    2. Specify if to **Select existing** COS bucket specification or if you want to **Add manually**.
    3. **Select a COS instance** or specify its name manually.
    4. **Select a bucket** or specify its name manually.
    5. Select the HMAC **Access secret** needed to authenticate to the COS instance.
    6. Click **Create** to create the persistent data store.

## Step 3: Mount the data store into a workload by using the console
{: #pds-mount-workload-ui}
{: ui}

After you create the persistent data store, you can mount it as **Volume mount** when you create or update an application or job.

### Mounting into an application
{: #pds-mount-app-ui}
{: ui}

1. Navigate to your app.
    * From the [Code Engine Projects page](https://cloud.ibm.com/codeengine/projects){: external}, click the name of your project. Click **Applications** to work with your applications.
    * From the Applications page, click the name of the application that you want to update or create a new one by clicking **Create**.

2. Select the **Configuration** tab.
3. From the **Volume mounts** tab, click **Add**.
4. Select **Volume type** as **Persistent data stores**.
5. Select a **Persistent data store**.
6. Specify a relative **Bucket subpath (optional)** if your application should access objects in the bucket with that subpath prefix only, for example `path/in/bucket`. This is useful when you want to isolate access to a specific folder within the bucket. The subpath must be a valid prefix in your COS bucket. Only the contents under that path will be accessible from the mounted directory.
7. Specify **Mount path**. This is the directory inside the application container where the data of the volume mount can be accessed, for example at `/mnt/bucket`.
8. Select a value for **Access permissions**, that is **Read-write** or **Read-only**.
9. Click **Add** to create the volume mount.
10. Click **Deploy** to save your changes and deploy the app revision.

When you update your application, your app creates a new revision and routes traffic to that instance.

### Mounting into a job
{: #pds-mount-job-ui}
{: ui}

1. Navigate to your job page.
    * From the [Code Engine Projects page](https://cloud.ibm.com/codeengine/projects){: external}, click the name of your project. Click **Jobs** to work with your jobs and job runs.
    * From the Jobs page, click the **Jobs** tab, and click the name of the job that you want to update or create a new one by clicking **Create**.

2. Select the **Configuration** tab.
3. From the **Volume mounts** tab, click **Add**.
4. Select **Volume type** as **Persistent data stores**.
5. Select a **Persistent data store**.
6. Specify a relative **Bucket subpath (optional)** if your job runs should access objects in the bucket with that subpath prefix only, for example `path/in/bucket`. This is useful when you want to isolate access to a specific folder within the bucket. The subpath must be a valid prefix in your COS bucket. Only the contents under that path will be accessible from the mounted directory.
7. Specify **Mount path**. This is the directory inside the job run container where the data of the volume mount can be accessed, for example at `/mnt/bucket`.
8. Select a value for **Access permissions**, that is **Read-write** or **Read-only**.
9. Click **Add** to create the volume mount.
10. Click **Deploy** to save your changes and deploy the job.
11. Click **Submit job**.

## Before you begin
{: #pds-prereqs-cli}
{: cli}

Before you can work with persistent data stores, ensure that the following prerequisites are met.

- You must have an [IBM Cloud Object Storage instance](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-provision&format=markdown).
- You must create a service credential for your Object Storage instance with [**HMAC credentials**](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-uhc-hmac-credentials-main&format=markdown) enabled. The HMAC credential requires at least the **Writer** service access role to read from and write to the bucket. If you only need read access, choose the **Content Reader** service access role instead.
- You must install the IBM Cloud Object Storage plugin by running the following command:
  ```txt
  ibmcloud plugin install cloud-object-storage
  ```
  {: pre}

- You must have a bucket available in your Object Storage instance. For more information, see [Create a new bucket](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-ic-cos-cli&format=markdown#create-a-new-bucket).
- You must have a [Code Engine project](https://cloud.ibm.com/docs/codeengine?topic=codeengine-manage-project&format=markdown) and it must be selected as the current context.

## Step 1: Create an HMAC secret in Code Engine by using the CLI
{: #pds-create-secret-cli}
{: cli}

To securely access your COS bucket, Code Engine requires the HMAC credentials that are associated with your Object Storage instance. You store these credentials in a secret within your Code Engine project.

To create a secret of format `hmac`, use the **`secret create`** command.

```bash
ibmcloud ce secret create --name my-hmac-secret --format hmac --secret-access-key-prompt --access-key-id-prompt
```
{: pre}

Provide the corresponding values from your COS service credential when prompted by the **`secret create`** command.

## Step 2: Create a persistent data store by using the CLI
{: #pds-create-datastore-cli}
{: cli}

Now, create the persistent data store resource in Code Engine. This resource acts as a reference to your COS bucket and links it with the HMAC secret that you created.

```bash
ibmcloud ce persistentdatastore create --name my-cos-bucket-pds --cos-bucket-name my-cos-bucket --cos-access-secret my-hmac-secret
```
{: pre}

- Replace `my-cos-bucket-pds` with a unique name for your data store.
- Replace `my-cos-bucket` with the exact name of your COS bucket.
- Replace `my-hmac-secret` with the name of the HMAC secret.

## Step 3: Mount the data store into a workload by using the CLI
{: #pds-mount-workload-cli}
{: cli}

After you create the persistent data store, you can mount it when you create or update an application or job. Use the `--mount-data-store` option with the format `MOUNT_PATH=PDS_NAME`.

### Mounting into an application
{: #pds-mount-app-cli}
{: cli}

The following command creates an application named `myapp` and mounts the `my-cos-bucket-pds` data store to the `/mnt/bucket` directory inside the application container.

```bash
ibmcloud ce application create --name myapp --image icr.io/codeengine/helloworld --mount-data-store /mnt/bucket=my-cos-bucket-pds
```
{: pre}

### Mounting into a job
{: #pds-mount-job-cli}
{: cli}

Similarly, this command creates a job named `myjob` and mounts the same data store to the `/mnt/bucket` directory.

```bash
ibmcloud ce job create --name myjob --image icr.io/codeengine/helloworld --mount-data-store /mnt/bucket=my-cos-bucket-pds
```
{: pre}

### Mounting a subpath within the bucket
{: #pds-mount-subpath-cli}
{: cli}

You can also mount a specific subpath within your COS bucket by appending the relative path to the mount definition using a colon (`:`). This is useful when you want to isolate access to a specific folder within the bucket.

For example, to mount only the `path/in/bucket` directory from the `my-cos-bucket-pds` data store into `/mnt/bucket`:

```bash
ibmcloud ce application create --name myapp --image icr.io/codeengine/helloworld --mount-data-store /mnt/bucket=my-cos-bucket-pds:path/in/bucket
```
{: pre}

Or for a job:

```bash
ibmcloud ce job create --name myjob --image icr.io/codeengine/helloworld --mount-data-store /mnt/bucket=my-cos-bucket-pds:path/in/bucket
```
{: pre}

> **Note:** The `path/in/bucket` must be a valid prefix in your COS bucket. Only the contents under that path will be accessible from the mounted directory.

## Step 4: Accessing files in the mounted data store
{: #pds-access-files}

Once your application or job is running, the code can interact with the mounted COS bucket as if it were a local directory. All standard file system operations are supported.

For example, inside your container, you can list files, read content, and write new files:

```bash
# List files in the bucket
ls -l /mnt/bucket

# Read a file from the bucket
cat /mnt/bucket/my-document.txt

# Write a new file to the bucket
echo "Hello from Code Engine" > /mnt/bucket/new-file.txt
```
{: pre}

## Limitations
{: #pds-limitations}

The mount is implemented using [`s3fs`](https://github.com/s3fs-fuse/s3fs-fuse){: external}, which provides a FUSE-based file system interface to S3-compatible storage. Be aware of the following limitations:

- **Number of persistent data stores:**
  - There is a restriction allowing a maximum of two persistent data store mounts per application or job.
- **Performance:**
  - Object Storage has high latency for the time-to-first-byte, making them slower than local file systems for operations that require immediate access.
  - Operations that modify files, such as random writes or appends, require rewriting the entire object in the backend, which can be slow and inefficient as there is no random write access.
  - Metadata operations, like listing directories, can have poor performance.
- **Consistency:**
  - IBM Cloud Object Storage provides strong read-after-write consistency for new objects, but eventual consistency for object overwrites and deletes. This means that after an update or deletion, read operations might temporarily return stale data.
  - Changes made to the bucket from outside the mount (for example, directly via the COS API or another client) are not immediately detected and might not be visible for some time.
- **File System Semantics:**
  - Standard POSIX file system features are not fully supported. Specifically, there are **no atomic renames** of files or directories and **no hard links**.
- **Concurrency:**
  - There is no coordination between multiple clients (for example, multiple app instances) mounting the same bucket. Concurrent writes to the same file from different instances can lead to data loss or corruption.
- **Event Subscriptions:**
  - If you have configured an event subscription for your Object Storage bucket, be aware that file create operations performed through the mount may generate multiple update events. This can result in your Code Engine app or job being triggered more than once for a single file operation, which may affect downstream processing or event-driven workflows.

Due to these limitations, this feature is not suitable for all workloads. It is best suited for workloads that primarily read large files, such as in deep learning or data analytics, where good throughput can be achieved. It is not recommended for workloads that require low latency, frequent small writes, or transactional file operations.

## Next steps
{: #pds-next-steps}

Now that you understand how to work with persistent data stores, explore more advanced topics:

- [Working with applications in Code Engine](https://cloud.ibm.com/docs/codeengine?topic=codeengine-application-workloads&format=markdown)
- [Working with jobs and job runs](https://cloud.ibm.com/docs/codeengine?topic=codeengine-job-plan&format=markdown)
- [Working with secrets](https://cloud.ibm.com/docs/codeengine?topic=codeengine-secret&format=markdown)
- [Working with the IBM Cloud Object Storage event producer](https://cloud.ibm.com/docs/codeengine?topic=codeengine-eventing-cosevent-producer&format=markdown)
- [IBM Cloud Object Storage Documentation](https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-getting-started-cloud-object-storage&format=markdown)