Data sovereignty
Your reconciliation data lives in your own GCS bucket, in your own GCP project. DataRecs accesses it only when running your reconciliation jobs.
BYOS lets your organization store reconciliation data artifacts — the parquet files and analysis outputs produced by your reconciliation jobs — in a GCS bucket you own and control, rather than DataRecs’ platform-managed storage.
Data sovereignty
Your reconciliation data lives in your own GCS bucket, in your own GCP project. DataRecs accesses it only when running your reconciliation jobs.
Zero-downtime migration
The migration copies your data while reads continue uninterrupted. Writes are paused only during the active copy window (typically minutes).
Fully reversible
Changed your mind? Revert to platform-managed storage at any time — the same pipeline copies data back.
Verified integrity
Every copied object is verified by count, size, and CRC32C checksum before the migration is marked complete.
The migration proceeds through a series of automated phases. You trigger it with a single API call or Console click, and it runs to completion without further intervention.
| Phase | Duration | What happens |
|---|---|---|
| Lock acquisition | Instant | Exclusive lock prevents concurrent migrations on your tenant. |
| Write pause | Instant | New data writes are temporarily paused (reads continue). Scheduled reconciliation jobs are suspended. |
| Drain | 0–60s | Any currently-running reconciliation job is allowed to finish (or gracefully stopped if it exceeds the deadline). |
| Copy | Minutes | Data artifacts are streamed from platform storage to your GCS bucket (or vice versa for a revert). |
| Verify | Seconds | Object counts, total sizes, and per-file checksums are compared to confirm integrity. |
| Finalize | Instant | Your storage mode is switched, scheduled jobs resume, and the write pause is lifted. |
Only reconciliation data artifacts are migrated:
Workflow logs, system metadata, and intermediate processing files are not migrated — they remain in platform storage and do not affect your reconciliation results.
Where your artifacts live (platform storage vs. your own bucket) and how they are encrypted are two separate choices. The artifact encryption posture lets you pick from four combinations, trading off convenience against how much you can read your own data — and how zero-knowledge it is to DataRecs.
| Posture | Where it’s stored | How it’s encrypted | Can you read it? |
|---|---|---|---|
| Platform managed (default) | DataRecs platform bucket | A key DataRecs manages for you | No |
| Your bucket, our key | Your GCS bucket | A key DataRecs manages for you | No |
| Your bucket, your key (BYOK) | Your GCS bucket | Your own Cloud KMS key | Yes |
| Your bucket, no encryption | Your GCS bucket | Not encrypted by DataRecs | Yes |
Changing your posture re-encrypts and/or relocates every existing artifact to match the new posture. This runs as a background migration — the same locked, verify-before-delete pipeline as a BYOS storage migration:
curl -X POST https://{your-api-domain}/data-storage/artifact-posture \ -H "Authorization: Bearer {your-api-key}" \ -H "Content-Type: application/json" \ -d '{ "posture": "byos-tenant-encrypted" }'Valid posture values: platform, byos-platform-encrypted, byos-tenant-encrypted, byos-plaintext. The request is rejected (HTTP 400) with BYOS_NOT_CONFIGURED if a “your bucket” posture is chosen before BYOS is set up, or BYOK_NOT_CONFIGURED if byos-tenant-encrypted is chosen before BYOK is configured.
storage_mode only changes after the copy AND verification both succeed. If anything fails, you stay on your current storage.Before starting a BYOS migration:
Create a bucket in your GCP project:
gcloud storage buckets create gs://my-company-datarecs-data \ --project=my-gcp-project \ --location=us-central1 \ --uniform-bucket-level-accessGrant the DataRecs tenant service account access to your bucket. The service account follows the pattern:
tenant-{your-tenant-id}@{datarecs-project}.iam.gserviceaccount.comYou can find your exact service account in the Console under Settings → Storage → Service Account, or from the /data-storage API endpoint.
Grant these roles on the bucket:
# Replace with your actual values (find your exact SA in Settings → Storage)SA="tenant-abc123@<datarecs-project>.iam.gserviceaccount.com"BUCKET="my-company-datarecs-data"
# Object Admin — read, write, delete objectsgcloud storage buckets add-iam-policy-binding gs://$BUCKET \ --member="serviceAccount:$SA" \ --role="roles/storage.objectAdmin"
# Legacy Bucket Owner — required for bucket-level listinggcloud storage buckets add-iam-policy-binding gs://$BUCKET \ --member="serviceAccount:$SA" \ --role="roles/storage.legacyBucketOwner"Tell DataRecs about your GCS bucket so it can validate access.
curl -X POST https://{your-api-domain}/data-storage/config \ -H "Authorization: Bearer {your-api-key}" \ -H "Content-Type: application/json" \ -d '{ "gcp_project_id": "my-gcp-project", "bucket_name": "my-company-datarecs-data", "bucket_region": "us-central1" }'A successful response returns your current storage configuration (configuring the bucket runs the access check; if it fails the request is rejected):
{ "storage_mode": "Platform", "storage_provider": "GCS", "byos_gcp_project_id": "my-gcp-project", "byos_bucket_name": "my-company-datarecs-data", "byos_bucket_region": "us-central1", "byos_migration_status": "not_started", "tenant_service_account": "tenant-abc123@datarecs.iam.gserviceaccount.com"}resource "datarecs_storage_bucket" "byos" { gcp_project_id = "my-gcp-project" bucket_name = "my-company-datarecs-data" bucket_region = "us-central1"}Once your configuration is validated, trigger the migration.
curl -X POST https://{your-api-domain}/data-storage/migrate \ -H "Authorization: Bearer {your-api-key}" \ -H "Content-Type: application/json" \ -d '{}'Response:
{ "status": "in_progress", "message": "Storage migration started. Reconciliation data is being copied to your GCS bucket."}The Settings → Storage page shows real-time migration status with a progress indicator.
Poll the storage endpoint:
curl -H "Authorization: Bearer {your-api-key}" \ https://{your-api-domain}/data-storageStatus values:
in_progress — migration is runningcompleted — migration finished successfullyfailed — migration encountered an error (see byos_migration_error)Once the migration reports completed:
storage_mode is now BYOSYou can verify your data is in GCS:
gcloud storage ls gs://my-company-datarecs-data/tenants/{your-tenant-id}/ --recursiveIf you need to switch back to platform-managed storage:
curl -X POST https://{your-api-domain}/data-storage/revert \ -H "Authorization: Bearer {your-api-key}" \ -H "Content-Type: application/json" \ -d '{}'The revert follows the same phases as the forward migration: lock → pause → drain → copy (GCS → Garage) → verify → finalize. Your storage_mode returns to Platform only after all data is verified back in platform storage.
If you revoke the service account’s GCS access while a migration is running:
storage_mode stays unchanged (on whatever it was before).byos_migration_error.To retry: restore the IAM permissions, then trigger the migration again.
If the DataRecs platform experiences an interruption during your migration:
storage_mode stays unchanged.Migrations have a maximum runtime (scaled to your data volume, up to 2 hours for very large tenants). If the maximum is exceeded:
Q: Can I use a bucket in a different GCP project than where DataRecs runs?
Yes. The bucket can be in any GCP project, as long as you grant the DataRecs service account the required roles on the bucket.
Q: Is my data deleted from platform storage after migration?
Not immediately. Platform storage retains your data per standard retention policies. This ensures that a revert is always possible without data loss.
Q: What about encryption?
Your data is encrypted by GCS using Google-managed keys (or your own CMEK if configured on the bucket). This is independent of DataRecs’ application-level envelope encryption, which protects data at the record level regardless of where it’s stored. To control how the reconciliation artifacts themselves are encrypted — including making them readable to you with your own KMS key — see Artifact encryption posture above.
Q: Can I restrict which regions my data is stored in?
Yes — you control the bucket’s location settings. DataRecs writes data to whatever bucket you configure, respecting your region choices.
Q: Will my reconciliation jobs be slower after migrating to BYOS?
Performance depends on network proximity between your DataRecs cell and your GCS bucket. If both are in the same or a nearby region, performance is comparable to platform storage. Cross-region configurations may add latency.
Q: How often can I migrate?
As often as needed. Each migration (forward or revert) takes a few minutes. However, writes are paused during migration, so avoid triggering migrations during business-critical reconciliation windows.
When configuring a bucket fails, the response carries an error_code describing the access problem.
Migration-control and posture-control failures surface as HTTP status codes.
| Symptom | Meaning | Resolution |
|---|---|---|
409 on migrate | A migration is already running. | Wait for it to complete, or contact support if it appears stuck. |
400 on migrate | BYOS bucket configuration is missing or invalid. | Configure your bucket in Settings → Storage first. |
BYOS_NOT_CONFIGURED (400) on set-posture | You chose a “your bucket” encryption posture before configuring BYOS. | Configure Bring Your Own Storage first, then set the posture. |
BYOK_NOT_CONFIGURED (400) on set-posture | You chose the byos-tenant-encrypted (your-key) posture before configuring BYOK. | Configure Bring Your Own Key first, then set the posture. |
error_code: BUCKET_NOT_FOUND | The named bucket doesn’t exist or isn’t reachable. | Check the bucket name and that it exists in the given project. |
error_code: INSUFFICIENT_PERMISSIONS | The service account can’t read/write the bucket. | Grant roles/storage.objectAdmin. |
error_code: LIFECYCLE_PERMISSION_MISSING | Missing bucket-level access the migration needs. | Grant roles/storage.legacyBucketOwner in addition to objectAdmin. |
error_code: BUCKET_NOT_EMPTY | The target bucket already contains objects. | Use a dedicated, empty bucket for DataRecs. |
error_code: SA_IMPERSONATION_FAILED | The DataRecs service account couldn’t be impersonated. | Re-check the IAM bindings on the service account and bucket. |
error_code: STORAGE_UNAVAILABLE | GCS was temporarily unreachable. | Transient — retry shortly. |
Write returns 503 | The write fence is active during migration. | Wait for migration to complete. Reads still work. |