BIGTABLE → STACKIT · ARCHITECTURE

Bigtable migration: designing the wide-column layer

STACKIT has no managed wide-column service, so Bigtable is a design decision before it is a migration. StackToIT classifies the instance as REDESIGN, writes no Terraform for it and names the settings a person must settle: the data model, replication, cluster zones and names. This page lays out the realistic options, what each costs you in operations and rewriting, and how to choose from what your code and your data already tell you.

A Bigtable instance and its policies, assessed

An estate written for this page and assessed by StackToIT on 4 November 2026: one instance with two clusters, a table with two column families, two garbage collection policies and an application profile. The right pane is a verbatim excerpt of engineering/architect-report.md for the instance: the reason, the table it includes and the three warnings about its uncatalogued neighbours. The run wrote no Terraform for any of the four units.

Example inputmain.tf
resource "google_bigtable_instance" "telemetry" {
  name                = "telemetry"
  deletion_protection = true

  cluster {
    cluster_id   = "telemetry-ew3-a"
    zone         = "europe-west3-a"
    num_nodes    = 3
    storage_type = "SSD"
  }

  cluster {
    cluster_id   = "telemetry-ew3-b"
    zone         = "europe-west3-b"
    num_nodes    = 3
    storage_type = "SSD"
  }
}

resource "google_bigtable_table" "readings" {
  name          = "device-readings"
  instance_name = google_bigtable_instance.telemetry.name
  split_keys    = ["a", "m", "t"]

  column_family {
    family = "metrics"
  }

  column_family {
    family = "meta"
  }
}

resource "google_bigtable_gc_policy" "metrics_ttl" {
  instance_name = google_bigtable_instance.telemetry.name
  table         = google_bigtable_table.readings.name
  column_family = "metrics"

  max_age {
    duration = "720h"
  }
}

resource "google_bigtable_gc_policy" "meta_versions" {
  instance_name = google_bigtable_instance.telemetry.name
  table         = google_bigtable_table.readings.name
  column_family = "meta"

  max_version {
    number = 1
  }
}

resource "google_bigtable_app_profile" "ingest" {
  instance       = google_bigtable_instance.telemetry.name
  app_profile_id = "ingest"

  single_cluster_routing {
    cluster_id                 = "telemetry-ew3-a"
    allow_transactional_writes = false
  }

  ignore_warnings = true
}
Excerpt of the architect reportengineering/architect-report.md
- **Why:** STACKIT has no wide-column database service; row-key design and the HBase/Bigtable client API move to a self-operated store or a redesigned data model.
- **Includes:** `google_bigtable_table.readings`
- **WARNING** (uncatalogued-related): google_bigtable_app_profile.ingest (google_bigtable_app_profile) is linked to this unit but not in the knowledge base; its effect on the migration is not assessed.
- **WARNING** (uncatalogued-related): google_bigtable_gc_policy.meta_versions (google_bigtable_gc_policy) is linked to this unit but not in the knowledge base; its effect on the migration is not assessed.
- **WARNING** (uncatalogued-related): google_bigtable_gc_policy.metrics_ttl (google_bigtable_gc_policy) is linked to this unit but not in the knowledge base; its effect on the migration is not assessed.
  • Four units, none drafted

    The table travels with the instance as a facet. The two garbage collection policies and the application profile are separate units classed MANUAL_REVIEW, because they are not in the engine's catalogue: nothing about them is assessed or drafted, and the run says so.

  • Why the confidence is LOW here

    The same instance alone, in the twelve-resource estate of our service mapping page, came out as MEDIUM. Here the architect report lists the instance under the linked units of the uncatalogued garbage collection policies with a confidence cap of LOW. That tells you the policies and the profile need an architect's eyes, not that the instance is more or less portable.

What the run classifies

UnitClass and confidenceWhy
Bigtable instance (with its table)REDESIGN, LOWSTACKIT has no wide-column database service. Row-key design and the HBase or Bigtable client API move to a self-operated store or a redesigned data model. Target named: a self-managed store on SKE, or MongoDB Flex.
Garbage collection policy, 30 days (max_age)MANUAL_REVIEW, LOWNot in the catalogue. Carries the retention rule of one column family; an architect decides where it lives.
Garbage collection policy, one version (max_version)MANUAL_REVIEW, LOWNot in the catalogue. Carries the version rule of the other column family.
Application profile with single-cluster routingMANUAL_REVIEW, LOWNot in the catalogue. Decides which cluster an application talks to; a store without that notion needs the choice made elsewhere.

Data movement reads DECISION REQUIRED with the mechanism UNKNOWN: the source states neither the size of the data nor its change rate, and the run does not guess them.

The options, with their trade-offs

The first two are the targets the engine names. The last two are general practice the engine does not propose; they fit only when the workload is smaller or colder than a Bigtable deployment suggests.

OptionWhat it meansTrade-offs
Self-managed wide-column store on SKE (the run names Apache Cassandra or HBase as examples)Closest data model: row or partition keys, column families, timestamped cellsYou operate it: upgrades, backups, capacity and repair. The client API changes unless you pick HBase. Highest operational load.
MongoDB Flex with a redesigned document modelSTACKIT documents it as a managed MongoDB service, compatible with native MongoDBKey-range access becomes an index or shard-key design. The schema is rewritten, not moved. Check the volume and write rate you actually have against the service.
PostgreSQL Flex with partitioned tables (general practice)Time or device partitions replace row-key rangesManaged and relational, with a rewrite of every access path. Sensible for moderate volume, not for unbounded writes.
Object Storage for cold history (general practice)Expired or rarely read rows land as filesCheap and durable, no low-latency lookups. Usually a complement to another option, not a replacement.

Where each Bigtable construct goes

Bigtable constructWhat it doesWhat you decide
Row keyThe only indexed value; rows are stored sorted by it, so key design drives how writes spread and how ranges readWhich queries must stay a single range read. Google's schema guidance warns against timestamp-first keys because of hotspots.
Column families and qualifiersGroup related columns; each cell holds timestamped versionsNames are open settings in the run. Decide whether versions matter at all.
Garbage collection policyAge and version rules per column family, applied by a background processThe target needs its own expiry. Bigtable can still return expired cells until compaction runs, so check whether anything depends on that.
Two clusters in two zonesReplication starts when a second cluster joins; instances with more than one cluster default to eventual consistencyReplication and cluster zone are open settings. Decide the placement of replicas on STACKIT and the consistency your readers accept.
Application profileRoutes an application's requests; in the example, single-cluster routing pins ingest to telemetry-ew3-aPin each workload to a cluster or accept any; the target store will not have the object.

How to choose

  1. 1. Read the access pattern out of the code

    List the queries: point reads by key, prefix or range scans, time-ordered reads per device. Range scans on a composite key are what a wide-column store does best and what every other option must rebuild.

  2. 2. Get the numbers the run cannot give you

    Data size, change rate and write throughput are not in the Terraform. The data-movement file states that size and change rate are not in the source and that tolerated downtime and recovery point were not provided; collect all of them from the running system before you shortlist anything.

  3. 3. State the consistency your readers accept

    A multi-cluster Bigtable instance reads eventually consistent by default. If that was a deliberate choice, a single primary with a replica may do; if nobody noticed, say so now.

  4. 4. Write down retention as a requirement

    The 30-day and one-version rules in the example are requirements, not settings to copy. Name the retention in business terms, then express it in the target.

  5. 5. Count the operating cost

    A self-managed store buys the closest model and costs a team that can run it. A managed service lowers that cost and raises the rewrite. The run prices neither.

  6. 6. Plan the data movement last, not first

    Mechanism, window and validation depend on the target. Choose them after the store, with rollback in mind: keep Bigtable readable until the new store has served real traffic.

Questions architects ask

Does STACKIT offer a managed Bigtable equivalent?

The engine finds none: its reason for the instance is that STACKIT has no wide-column database service. The targets it names are a self-managed store on SKE or MongoDB Flex, both after a redesign.

Why are the garbage collection policies MANUAL_REVIEW?

They are not in the engine's catalogue, so nothing about them is assessed or drafted. They still matter, because they hold your retention rules.

Can StackToIT move the Bigtable data?

No. It never moves data. The run lists the instance as a stateful unit with the mechanism undecided, and leaves size, change rate and tolerated downtime to you.

Is a redesign always a rewrite of the application?

It is a rewrite of the data access layer in most cases. Choosing a store with the same model, such as HBase, narrows that change, at the price of running it yourself.

Sources

Your next move: STACKIT.

Tell us about your estate. We show you what StackToIT delivers for it: target architecture, Terraform artifacts and a structured migration plan.