Supported environments
- Akamai
- Azure
- DigitalOcean
- Google Cloud
- OCI
- Private Kubernetes
- Scaleway
How the backends compare
Each row compares a capability of SQS (FIFO) with its adaptation on each backend. A dash means this profile does not state the capability for that backend.Cloud Adapter
On Akamai, Azure, DigitalOcean, OCI, Private Kubernetes, and Scaleway
PostgreSQL
PostgreSQL hosting
Tensor9 operates CloudNativePG inside the customer’s Kubernetes cluster. Queue data is stored on that cluster’s volumes and does not survive a full cluster rebuild. Plan recovery and message cutover before replacing the cluster. Tensor9 operates the queue schema and adapter. Queues start empty; existing SQS messages are not migrated. Drain each message group before cutover to preserve order.Persistent queue management and total cost
Cloud Adapter retains a persistent PostgreSQL store for the queue catalog, tenancy and lifecycle/control state, normally shared with the Cloud Adapter deployment. Native broker or Cosmos message storage does not remove this resource. Include its allocated compute, storage, backups and selected HA costs alongside adapter and message-backend charges; an idle or serverless message backend does not imply a zero total installation floor. Backend-only curves omit these shared allocations unless their assumptions explicitly include them. This control store is distinct from the SQS-owned message database. PostgreSQL-authority FIFO composites add recoverable message bodies, receipts, deduplication and outbox state to an explicitly configured SQS message database; they do not store messages in the shared control catalog. A separate logical database and login provide data/permission separation, but still share server CPU, storage, IOPS, WAL and connection limits when hosted on the same instance. Dedicated physical server/instance capacity is a separate allocation and cost decision.Database placement and recovery
CloudNativePG keeps message tables on your Kubernetes cluster’s persistent volumes. Tensor9 operates the database and adapter. Replacing the cluster requires an explicit data recovery or drained cutover procedure; a new empty cluster is not a recovery of the old queues. This placement shares cluster resources with the application.Capacity and queue workload
The default shared message database holds multiple queues, each with its own table. Dedicated physical server/instance capacity isolates compute and I/O from other server workloads; a separate logical database alone does not. HA changes recovery, commit latency and price rather than FIFO semantics. Neither choice creates an unlimited queue service. Size connection pools, storage, IOPS and WAL for accepted sends, receives, deletes, visibility changes, retries and cleanup together. Long polls wait outside database transactions. The single-message receive mechanism below permits one message in flight per group. If a group takes T seconds from receive to settlement, its useful completion rate is bounded by roughly 1/T, even when other groups are idle. A larger MaxNumberOfMessages can collect heads from multiple groups; it does not create a ten-message pipeline within one group. Adding consumers or database CPU does not remove that serialization. Compare the separate ordered-batch design before selecting a workload that depends on within-group batching. Requested live counts scan the message population even for a single requested counter. Frequent depth polling over a large backlog competes for database I/O and pool capacity; receipt classification can change index/heap work. Price those queries separately from sends and completed message cycles. A fall in depth can reflect purge, expiry or dead-letter transfer rather than application completion. The portable Standard-queue benchmark does not establish the capacity of this host, its HA configuration or a FIFO workload. Payload sizes, active-group skew, settlement time, backlog growth and matched native measurements determine whether a proposed size fits. Missing measurements leave capacity unknown.Retries, batches and application changes
The application keeps its SQS SDK and uses the adapter’s configured endpoint and authentication. Backend IAM, database schema permissions and TLS identity belong to the deployment; an AWS ARN or policy is not automatically a target-cloud authorization grant. Scope identities to the customer resources and keep rotated credentials out of message bodies and receipt handles. A batch response reports each entry separately. Retry only failed entries whose outcome is known; a request timeout can follow a committed send or delete. Keep the same effective deduplication ID on uncertain retries. Duplicate enqueue suppression does not make consumer side effects exactly once. SDK retries and adapter retries share one bounded deadline, with backoff for provider throttling. An expired observer deadline does not prove a still-running native operation was cancelled. Visibility expiration permits another delivery while an earlier worker can still be executing. Consumers use idempotent writes, choose a visibility duration that covers normal processing and handle stale receipt errors. Retention can expire a message in flight. Queues start empty: drain the source before cutover, group by group. Queue recreation and purge must invalidate old claims independently of public names; data cleanup can continue after logical retirement. Database or broker backup is a resource recovery mechanism, not an automatic replay of application side effects.PostgreSQL queue behavior
Your application keeps its SQS SDK and uses the authenticated Cloud Adapter endpoint configured for the install. The adapter performsSendMessage and ReceiveMessage in the SQS-owned PostgreSQL message database and returns SQS responses, error codes and MD5 checksums. Its message-data login is separate from other services and the shared control catalog.
Each queue is a PostgreSQL table with one row per message. Sending, receiving, deleting, delays, visibility, dead-letter delivery and message counts all work on those rows. FIFO queues add ordering by message group, per-group sequence numbers and duplicate detection. Consumers can still receive a message more than once.
The application keeps its SQS SDK. The adapter stores each queue in a PostgreSQL table.
Architecture
The adapter keeps all queue state in PostgreSQL, including messages and receipt handles, so adapter instances can restart or scale out without losing track of in-flight messages. On Cloud SQL and Azure Flexible Server it signs in with short-lived Cloud SQL IAM or Microsoft Entra tokens used as database passwords, so no static secret is stored. When the stack is deployed, Tensor9 creates one database per Cloud Adapter deployment and one table per declared queue. Each row holds the message body and attributes, its message group, its visibility time, its receipt handle, its receive count and the time it was sent. A FIFO queue orders messages within each message group; each row’s arrival position gives its sequence number. A dead-letter queue is another queue table, and a background task deletes messages older than the queue’s retention period. CloudNativePG, Cloud SQL for PostgreSQL, Azure Flexible Server and Scaleway use the same adapter code and tables. They differ in where the data lives: the managed servers run outside your Kubernetes cluster, while CloudNativePG runs inside it. See the rebuild limitation below.Each queue, including each dead-letter queue, is a PostgreSQL table. The same adapter runs on every supported PostgreSQL host.
Receiving messages
One database step selects messages whose visibility timeout has passed, oldest first, up to the requested batch size. In the same step it gives each a new receipt handle, hides it for the visibility timeout, adds one to its receive count and returns it. Messages another receiver is taking at that moment are skipped. FIFO queues return the next eligible message in each group, keeping one in flight per group. When the visibility timeout passes, the message can be delivered again; that does not stop a worker still processing the earlier copy.ApproximateReceiveCount is the actual number of receives, not an estimate. The MD5 checksums of the body and attributes are recomputed, so your SDK’s checks pass. DelaySeconds sets when a message first becomes visible. Long polling waits up to WaitTimeSeconds (at most 20 seconds) and returns as soon as a message is available. SendMessageBatch inserts all entries at once and reports a result for each entry. Message bodies are stored in the queue table.
Two receivers never get the same message at the same time. ApproximateReceiveCount is the actual receive count.
Receipt handles & visibility
Each receive saves a new receipt handle with the message.DeleteMessage and ChangeMessageVisibility find the message by that handle, including after an adapter restart or through another adapter instance.
A delete or visibility change whose handle matches no message returns ReceiptHandleIsInvalid. That includes a message already deleted, or received again under a newer handle. The visibility timeout defaults to 30 seconds. ChangeMessageVisibility can extend it with no lock-duration maximum, and zero makes the message available again immediately. Retention can delete a message while it is in flight.
Receipt handles are saved with messages, so they still work after an adapter restart. Visibility has no lock-duration limit.
Dead-letter & retention
When source and DLQ belong to the same supported SQS-owned message database transaction, receive moves messages atmaxReceiveCount atomically with claiming the rest. Both changes commit or neither does. Cross-database/store transfers are unsupported: sharing a provider, physical server or control log is not a shared message transaction, and no other service’s tables are used. The DLQ retains ordinary queue operations and cleanup. A FIFO move creates a new message in the DLQ, with a new MessageId, a receive count of zero and a new send time.
A background task deletes messages sent longer ago than the queue’s retention period, including messages in flight; receiving does not reset that time. The retention period defaults to four days and is kept between 60 seconds and 14 days, so a missing or too-short value cannot delete new messages straight away. One worker per database removes expired messages in batches, pauses during database maintenance, and continues if one queue fails. Limits on rows per pass and time per batch cap the load.
Atomic DLQ moves require the same supported SQS-owned database transaction. Cross-store moves are unsupported. Retention cleanup removes aged messages.
FIFO ordering & dedup
A FIFO queue stores each message’sMessageGroupId and orders delivery within each group. A receive returns only the oldest message of each group that has nothing in flight (no message in that group is currently received and still hidden). Because arrival positions only increase, that is always the group’s next message, and exactly one message is in flight per group at a time. Groups are independent, so different receivers can process different groups at once, coordinated only by PostgreSQL. When a message’s visibility timeout passes, it is first in its group again, so a redelivery stays in sequence.
Each FIFO send requires MessageGroupId and returns a SequenceNumber: the message’s arrival position as a 20-digit, zero-padded number.
Deduplication markers live in a separate PostgreSQL table keyed by queue and deduplication ID. An explicit MessageDeduplicationId takes precedence; otherwise, on a queue with content-based deduplication, the key is the SHA-256 of the body, excluding attributes. The message insert and deduplication marker are part of one transaction. A duplicate within 5 minutes saves no new message and returns the original MessageId and SequenceNumber. Marker retention is independent of message retention, so receiving or deleting the original does not shorten the deduplication window.
While a message is in flight, no other message from its group is delivered until it is deleted or its visibility timeout passes. That does not stop a timed-out worker from finishing a message it already received, so consumers must make repeated processing safe.
FIFO receives deliver one message per group at a time. Sends return a SequenceNumber, and repeated sends within 5 minutes are suppressed, matched by an explicit ID or, with content-based deduplication, a body hash.
Limitations
Where SQS and the PostgreSQL adapter differ- Throughput behaves differently: one PostgreSQL server serves every queue. All of a Cloud Adapter deployment’s queues share one server, so its capacity bounds peak throughput and a heavy queue can affect the others. In Tensor9’s round-trip test of a moderate-rate Standard queue, the adapter matched SQS throughput (about 300 vs 286 ops/s) with a lower p99 (140 ms vs 172 ms) but a slower median (p50 24 ms vs 15 ms). That is not a measured ceiling, and it does not cover FIFO queues or every host.
- Recovery follows the database placement. CloudNativePG keeps queue data on the Cloud Adapter deployment cluster’s volumes. Rebuilding the cluster requires explicit data recovery or a drained cutover.
- Messages are limited to 256 KiB by default. The adapter’s default limit is 262144 bytes, while native SQS now accepts up to 1 MiB. Sends are checked against the queue’s declared limit.
- FIFO send deduplication lasts 5 minutes. A duplicate send within that window returns the original IDs. Reusing an ID after the window can create a new message. Consumer redelivery remains possible even within the window.
- Stale receipt handles behave differently: they return an error.
DeleteMessageandChangeMessageVisibilityreturnReceiptHandleIsInvalidwhen no message matches the handle. - Retention behaves differently: expired messages are removed periodically. An expired message can remain until the next cleanup pass. Retention is kept between 60 seconds and 14 days; a too-short value is raised to 60 seconds so that new messages are not deleted.
- Counts observe queue state, not application completion. Requested message counts read the message database: eligible messages are visible, future-visible messages with a receipt are in flight, and future-visible messages without a receipt are initially delayed. These categories share one query snapshot and can change immediately afterward. Metadata-only reads do not require a message-table count. An unavailable requested count returns an explicit unsupported result rather than zero. Purge, expiry and dead-letter movement can reduce depth without completing the application’s work.
- Queue creation behaves differently: queues are created when the stack is deployed. Tensor9 creates the database and each queue’s table, and its dead-letter table, at deploy time.
CreateQueue,DeleteQueueandSetQueueAttributesact on those tables. Switching a queue between Standard and FIFO is rejected, because it would replace the queue.
Other considerations
- Moving from AWS. The database and queue tables start empty, and existing SQS messages are not migrated. Drain each group before switching it, to preserve order.
- Removing queues. Each queue is created in one step, so a crash never leaves a half-created queue. When a queue is removed from the stack, Tensor9 deletes only queues it created; any other queue is detached and left in place. A queue that still holds messages is not deleted unless deletion is forced.
- Who operates what. On the managed hosts, the provider operates the database’s durability, backups and high availability, and Tensor9 operates the adapter. On CloudNativePG, Tensor9 operates the database inside your cluster.
Example monthly charges
This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. How Tensor9 estimates costs explains the method and what the estimates include. Native or deployment mapping. FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability. Cost estimates describe the selected service resources; operation coverage remains separate.SQS FIFO · SQS request billing units
Feature: SQS FIFO. Estimated monthly service charges by SQS request billing units. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: us-central1; currency: USD.- 1-KiB messages, unbatched send/receive/delete; actual batch and delivery assumptions stay visible. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
- Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → us-central1, USD/month.
- Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
- Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
- Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve’s workload note.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Native/deployment comparison scope: FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Self-hosted target: PostgreSQL (PostgreSQL License, https://www.postgresql.org/about/licence/). Selected CPU, RAM and physical disk allocation grow with workload; no per-operation price is assumed. No vendor charge: the target runs on the customer’s Kubernetes nodes, so CPU, RAM and disk bill at the Kubernetes node reference rates, Compute Engine N2 in us-central1 (USD 0.031611/vCPU-hour, 0.004237/GiB-hour) with pd-balanced disk (0.10/GiB-month) and Premium Tier egress. The cost-optimized E2 series lists 0.02181159/vCPU-hour and 0.00292353/GiB-hour; AWS m6i/r6i and Azure D2s v5/E2s v5 both decompose to 0.033/vCPU-hour and 0.00375/GiB-hour. Requested CPU and RAM are billed; node bin-packing waste, system reservations and the cluster control-plane fee are not.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: Compute Engine n2-highmem-128 has 128 vCPUs and 864 GB (https://docs.cloud.google.com/compute/docs/general-purpose-machines); a Persistent Disk volume holds up to 64 TiB (https://docs.cloud.google.com/compute/docs/disks/persistent-disks).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
- AWS Price List API, AWSQueueService offer: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSQueueService/current/us-east-1/index.json
- Compute Engine general-purpose machine pricing: https://cloud.google.com/products/compute/pricing/general-purpose
- Disk and image pricing: https://cloud.google.com/compute/disks-image-pricing
- Network pricing: https://cloud.google.com/vpc/network-pricing
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
plan-2205b0bb4fecd035329ea8f524e1a885b9bdcdab / 2026-10-22.planning.2. Curve: workload-1.
Sources: AWS Price List API, AWSQueueService offer, Compute Engine general-purpose machine pricing, Disk and image pricing, Network pricing.
SQS FIFO → PostgreSQL: Authored native-usage planning example. Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.
Scenario source region: us-east-1. Scenario target region: us-central1. Currency: USD.
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
- Translated reads: 0 operations.
- Translated writes: 0 operations.
- Translated resident physical data: 0 GiB-month.
- Native provider operations: 0 operations.
- Published payload: 0 GiB.
- Delivered payload: 0 GiB.
- Allocated execution CPU: 0 vCPU-hour.
- Allocated execution RAM: 0 GiB-hour.
- Independent resource allocation: 0 resource-hour.
- Independent inventory: 0 resource-month.
- Input tokens: 0 tokens.
- Output tokens: 0 tokens.
- Billable network: 0 GiB.
- Dependent object sink retained data: 0 GiB-month.
- Dependent object sink writes: 0 writes.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Native/deployment comparison scope: FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Self-hosted target: PostgreSQL (PostgreSQL License, https://www.postgresql.org/about/licence/). Selected CPU, RAM and physical disk allocation grow with workload; no per-operation price is assumed. No vendor charge: the target runs on the customer’s Kubernetes nodes, so CPU, RAM and disk bill at the Kubernetes node reference rates, Compute Engine N2 in us-central1 (USD 0.031611/vCPU-hour, 0.004237/GiB-hour) with pd-balanced disk (0.10/GiB-month) and Premium Tier egress. The cost-optimized E2 series lists 0.02181159/vCPU-hour and 0.00292353/GiB-hour; AWS m6i/r6i and Azure D2s v5/E2s v5 both decompose to 0.033/vCPU-hour and 0.00375/GiB-hour. Requested CPU and RAM are billed; node bin-packing waste, system reservations and the cluster control-plane fee are not.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: Compute Engine n2-highmem-128 has 128 vCPUs and 864 GB (https://docs.cloud.google.com/compute/docs/general-purpose-machines); a Persistent Disk volume holds up to 64 TiB (https://docs.cloud.google.com/compute/docs/disks/persistent-disks).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
plan-2205b0bb4fecd035329ea8f524e1a885b9bdcdab / 2026-10-22.planning.2. Scenario: planning-example.
Sources: AWS Price List API, AWSQueueService offer, Compute Engine general-purpose machine pricing, Disk and image pricing, Network pricing.
On Azure
Azure Service Bus
Persistent queue management and total cost
Cloud Adapter retains a persistent PostgreSQL store for the queue catalog, tenancy and lifecycle/control state, normally shared with the Cloud Adapter deployment. Native broker or Cosmos message storage does not remove this resource. Include its allocated compute, storage, backups and selected HA costs alongside adapter and message-backend charges; an idle or serverless message backend does not imply a zero total installation floor. Backend-only curves omit these shared allocations unless their assumptions explicitly include them. This control store is distinct from the SQS-owned message database. PostgreSQL-authority FIFO composites add recoverable message bodies, receipts, deduplication and outbox state to an explicitly configured SQS message database; they do not store messages in the shared control catalog. A separate logical database and login provide data/permission separation, but still share server CPU, storage, IOPS, WAL and connection limits when hosted on the same instance. Dedicated physical server/instance capacity is a separate allocation and cost decision.Service Bus capacity and queue lifetime
Standard and Premium use the same AMQP mapping described below, with different resource isolation, configured message limits and charges. Standard shares namespace capacity; Premium reserves approved messaging units. A messaging unit is not a fixed messages-per-second guarantee. Check actual SKU, entity limits, sessions, duplicate-detection window and credential permissions before binding a queue. A larger native entity does not automatically raise the adapter’s declared message limit. Native receipts belong to broker receiver links. The configured five-minute visibility ceiling and restart limitation remain applicable in this native design. Losing a link or failing to observe settlement leaves an uncertain result; the adapter cannot turn lock loss into a successful delete. A consumer must tolerate redelivery and make external effects idempotent. Cloud Adapter manages logical queues against a predeclared inventory of fresh, exclusively owned native entities. A deleted name recreated later receives a different entity; old work can reach only the retired one. Allocation history is retained, and exhausted inventory refuses a create before messaging effects. This finite inventory constrains cumulative queue churn, including uncertain/failed births, rather than just peak active queues. Provisioning more inventory is an explicit customer resource action. Declared settings and tags are catalog state; live counts need separate management authority and are not fabricated from AMQP traffic.FIFO with PostgreSQL authority and broker wakeups
Native sessions provide group-ordered broker delivery, but do not create unlimited group concurrency or full SQS FIFO semantics. Receiver slots are bounded; unsettled heads occupy them, and a hot session can delay others. Broker duplicate detection suppresses duplicate transport sends; it does not preserve the original SQS MessageId/SequenceNumber response or durable ReceiveRequestAttemptId result. Native FIFO does not support ReceiveRequestAttemptId replay; that parameter requires a durable attempt authority and is explicitly unsupported. The native profile below keeps these differences visible. The coordinated alternative adds a dedicated customer Azure PostgreSQL database. It stores full recoverable bodies, per-group sequence, five-minute dedup response, receipt attempts, visibility and pending notifications in one transaction. Service Bus carries small versioned wakeups, not the authoritative message body. Send succeeds after the database commit; duplicate sends return the original durable result. A publisher retries wakeups with stable identity, and bounded database scans recover lost notifications. Receive claims only the oldest eligible authority messages. Delete and visibility changes compare the exact queue incarnation, purge generation and claim token. Restarting an AMQP link or releasing a notification session does not release a customer’s SQL claim. Late or duplicate wakeups cannot insert messages. This avoids pretending that a broker acknowledgement and a database commit are one atomic operation. The ordered-batch design conservatively blocks new group work until all unsettled members have expired or settled. Modified receive-attempt replays are explicitly unsupported; valid unchanged five-minute attempts replay the original set. This restriction remains distinct from the direct SQL engine’s one-in-flight-per-group mechanism. Neither version claims unlimited within-group parallelism. Cross-store dead-letter moves are unsupported. Standard/Premium affect notification costs and capacity, while PostgreSQL determines payload capacity, receipts and user visibility. Count both databases and broker operations, retained dedup/attempt state, outbox retries, repair scans and cleanup. Direct PostgreSQL is the simpler comparison when no broker integration justifies the extra resource. No native broker lock or message-size limit should be reused as the authority’s capacity estimate.How it works
Your application keeps its SQS SDK and uses the authenticated Cloud Adapter endpoint configured for the install. The adapter translatesSendMessage and ReceiveMessage to Azure Service Bus and returns SQS responses, error codes and MD5 checksums. Native sessions govern broker ownership; they do not grant Azure provisioning authority.
For a .fifo queue, Tensor9 provisions a Service Bus queue with sessions enabled. The adapter uses the MessageGroupId as the session ID, and the .fifo suffix tells it to receive by session. Service Bus gives each session to one consumer at a time, and the adapter delivers one message per group at a time, so send order holds across many consumer instances.
The application keeps its SQS SDK. A Tensor9 adapter translates FIFO queue calls to Service Bus sessions.
Architecture
The adapter talks to Service Bus Standard over AMQP 1.0. On send, it sets the session ID fromMessageGroupId. On receive, it delivers one message per group, renews the session lock while the visibility timeout runs, and completes or releases messages so their delivery counts stay correct. It signs in with your AKS Workload Identity, with no static secret.
Session receives run separately from sending and from standard-queue receives, so a FIFO receive never blocks them.
Tensor9 creates the queue when the stack is deployed, before the first message arrives, with sessions enabled, duplicate detection over a 5-minute window, a 5-minute session lock (ten times the adapter’s lock-renewal interval), dead-lettering of expired messages, and automatic forwarding to your dead-letter queue. Microsoft operates Service Bus’s durability, backups and high availability; Tensor9 operates the adapter.
Each session is one MessageGroupId , so each group keeps strict order with one message in flight.
How sessions preserve group order
A Service Bus session groups messages under one ID and gives one consumer exclusive access to it. While that consumer holds the session, no other consumer can receive its messages. Messages arrive in the order they were queued, and the adapter allows one message in flight per group. Service Bus assigns each active group to one consumer even when several application pods receive from the same queue, so your pods need no shared lock table, leader election or partition assignment.- One message in flight per group. A group’s next message is delivered only after the current one is deleted, as with the PostgreSQL FIFO option. This limits a single group to one message per round trip, in exchange for strict order.
- A slow consumer keeps its group. The adapter renews the session lock while your visibility timeout runs.
ChangeMessageVisibilitywith a longer timeout renews the lock; zero makes the message available again at once, in order. - Receive counts stay accurate. When the adapter gives up a session, it first releases the in-flight message so its delivery count goes up, moving a failing message toward its redrive limit instead of resetting it. It also receives no more messages than the remaining
MaxNumberOfMessages, so no message is received and dropped, which would raise its count.
Service Bus gives each group’s session to exactly one consumer, so order holds as you add consumer pods.
Duplicate detection
Service Bus duplicate detection keeps a 5-minute history. Sends with the same deduplication key within that window queue one message. A consumer can still receive that message again after its visibility timeout. Service Bus keeps the deduplication history, so the adapter tracks nothing extra. An explicitMessageDeduplicationId takes precedence. Otherwise the adapter uses a hash of the body on every .fifo send. It always sets this hash because its messaging permissions cannot read whether content-based deduplication is on. With duplicate detection enabled, Service Bus uses the hash to drop retries; with it disabled, the hash is only an ID. The adapter stores the SQS MessageId separately, as an application property, and returns it on receive, so equal-body messages sent outside the window keep distinct SQS IDs.
The adapter uses the MessageDeduplicationId, or a body hash, as the Service Bus message ID. Service Bus drops repeats within 5 minutes.
Dead-lettering
Service Bus dead-letters a message when its delivery count reaches the limit set bymaxReceiveCount. The next message in that group can then be delivered.
The adapter cannot receive from Service Bus’s built-in dead-letter subqueue, so Tensor9 sets up automatic forwarding to the dead-letter queue (DLQ) you declared, keeping the session ID. A FIFO queue needs a FIFO DLQ, which is created with sessions enabled. Messages whose time to live (TTL) expires are dead-lettered too, so you can inspect or recover them from the DLQ.
Declaring a non-.fifo DLQ for a .fifo queue stops the build with a clear error, rather than creating a queue whose dead letters would have nowhere valid to go.
Service Bus forwards messages that reach maxReceiveCount to your declared DLQ, where the adapter can receive them.
Limitations
Where SQS FIFO and Service Bus differ- Duplicate sends behave differently: the dropped send returns a new
MessageId. SQS returns the original message’sMessageId(andSequenceNumber) for a duplicate. Here the duplicate is still dropped (consumers can still get redeliveries), but its response contains a new ID that matches no delivered message. Do not wait for that ID. SequenceNumberis not returned on send. Service Bus cannot return its sequence number when a message is sent. Receive responses include it; it increases across the queue, and so within each group.- Visibility timeouts above 5 minutes are not supported. The visibility timeout maps to the session lock, which Tensor9 sets to 5 minutes, ten times the adapter’s renewal interval. A longer value returns an error rather than being shortened.
ChangeMessageVisibilityrenews the lock. - Receipt handles behave differently: they stop working when the adapter restarts. A handle needs a live session lock. After a restart, old handles are invalid, and the group’s in-flight message is delivered again, in order, when its session lock expires, within 5 minutes.
- Expiry behaves differently: it can affect a whole session. SQS retention applies to each message. On Service Bus, an expired message at the front can expire its whole session. Expired messages are dead-lettered and can be recovered from the DLQ, but more may expire together than on SQS.
- Single-group throughput behaves differently: one message per round trip. Strict order allows one message in flight per group, against up to 10 per receive on SQS. Total throughput grows with the number of groups, so parallelism comes from many groups, not from batching within one.
- Receives on an empty queue behave differently: they can wait longer than
WaitTimeSeconds. Service Bus controls how long accepting a session takes, and the adapter never cancels it partway, because that could leave a session lock held. A FIFO receive on an empty queue can overrun its wait by up to one accept window, about 60 seconds at worst; your monitoring shows the real figure on Azure. - Per-message
DelaySecondsis not supported. It is rejected, as SQS rejects it on a FIFO queue, because a delayed message would arrive after later messages in its group. For queue-level settings, Cloud Adapter manages the logical queue settings, but the messaging backend rejects a nonzero queue delay and new dead-letter routes. - You must drain a queue before changing its FIFO or deduplication settings. Sessions and duplicate detection are fixed when the queue is created. Changing between standard and FIFO, or turning content-based deduplication on or off, deletes and re-creates the queue and loses its messages. Every FIFO build warns about this.
- Sends without a deduplication ID behave differently: they are accepted. SQS requires
MessageDeduplicationIdwhen content-based deduplication is off. The adapter cannot read that setting with its messaging permissions, so it accepts the send. Group order is kept, but you do not get the SQS validation error.
Other considerations
- Moving from AWS. The Service Bus namespace and queue start empty, and messages in SQS are not migrated. Switch over when the queue is drained, or write to both queues for a while, and drain each group so none switches partway through.
- Who operates what. Tensor9 creates the namespace and the queue, configured as described under Architecture, from your queue declarations, and runs the adapter next to your application. The declared
maxReceiveCountsets when messages are forwarded to the DLQ. Microsoft operates Service Bus Standard: durability, backups and high availability. You operate the Azure subscription, cluster patching and monitoring. Sending and receiving need no queue-management credential. - FIFO must be selected explicitly. Older deployments that used the earlier combined SQS-to-Service-Bus option supported standard queues only. Tensor9 does not convert them to FIFO; declare and select a FIFO queue to use sessions.
Example monthly charges
This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. How Tensor9 estimates costs explains the method and what the estimates include.SQS FIFO · SQS request billing units
Feature: SQS FIFO. Estimated monthly service charges by SQS request billing units. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: East US; currency: USD.- 1-KiB messages, unbatched send/receive/delete; actual batch and delivery assumptions stay visible. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
- Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → East US, USD/month.
- Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
- Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
- Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve’s workload note.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Azure Service Bus Standard bills a namespace base charge that includes 13 million operations a month, then graduated per-operation prices: USD 0.80 per million to 100 million, 0.50 to 2,500 million and 0.20 beyond. An operation is any API call (send, receive, complete) per 64 KB of message; the family’s managed operations count calls, not 64 KB units. Standard has no storage charge (queue size quota up to 5 GB is included). More than 1,000 brokered connections bill USD 0.03 per connection-month, which this profile does not model.
- AWS Price List API, AWSQueueService offer: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSQueueService/current/us-east-1/index.json
- Azure Retail Prices API: https://prices.azure.com/api/retail/prices
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
plan-41a96e9bd678520a179bd0f5bb232496011160b0 / 2026-10-22.planning.2. Curve: workload-1.
Sources: AWS Price List API, AWSQueueService offer, Azure Retail Prices API.
SQS FIFO → Azure Service Bus: Authored native-usage planning example. Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.
Scenario source region: us-east-1. Scenario target region: East US. Currency: USD.
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
- Translated reads: 0 operations.
- Translated writes: 0 operations.
- Translated resident physical data: 0 GiB-month.
- Native provider operations: 0 operations.
- Published payload: 0 GiB.
- Delivered payload: 0 GiB.
- Allocated execution CPU: 0 vCPU-hour.
- Allocated execution RAM: 0 GiB-hour.
- Independent resource allocation: 0 resource-hour.
- Independent inventory: 0 resource-month.
- Input tokens: 0 tokens.
- Output tokens: 0 tokens.
- Billable network: 0 GiB.
- Dependent object sink retained data: 0 GiB-month.
- Dependent object sink writes: 0 writes.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Azure Service Bus Standard bills a namespace base charge that includes 13 million operations a month, then graduated per-operation prices: USD 0.80 per million to 100 million, 0.50 to 2,500 million and 0.20 beyond. An operation is any API call (send, receive, complete) per 64 KB of message; the family’s managed operations count calls, not 64 KB units. Standard has no storage charge (queue size quota up to 5 GB is included). More than 1,000 brokered connections bill USD 0.03 per connection-month, which this profile does not model.
plan-41a96e9bd678520a179bd0f5bb232496011160b0 / 2026-10-22.planning.2. Scenario: planning-example.
Sources: AWS Price List API, AWSQueueService offer, Azure Retail Prices API.
Azure Cosmos DB (queue)
How Cosmos serves SQS FIFO
The application keeps its SQS SDK, configured to use the adapter endpoint. Cosmos DB stores the message body and the state that makes it a queue: group sequence, duplicate-send result, current receipt, visibility deadline and lifecycle generation. Microsoft operates Cosmos; Tensor9 operates the adapter and queue procedures in the customer’s Azure environment. Queue-wide deduplication puts the whole queue in one logical partition. Explicit MessageGroup deduplication can put independent groups in separate partitions. This is a semantic choice, not a transparent throughput optimization: the latter can accept the same deduplication ID in two groups.Send, duplicate suppression and uncertain results
A partition-local procedure validates the queue generation, chooses the explicit MessageDeduplicationId or the SHA-256 body hash when content-based deduplication is enabled, and checks its five-minute expiry. Missing both forms is rejected. A live marker returns the original MessageId and SequenceNumber without another enqueue, including after the original message was consumed. A new send writes message, marker and next group sequence in one transaction. There is no reserved sequence without its message. Database-side acceptance time determines expiry; TTL only removes state after its logical lifetime. A lost response after commit is uncertain until the same effective deduplication identity resolves it. Never retry with a new ID merely because the network timed out. Batch sends split into same-partition chunks within transaction byte/operation limits, returning a result per entry. Some entries can commit while others fail; the entire SQS batch is not one transaction.Ordered receive, durable receipts and batch restrictions
Receive transactionally claims the earliest eligible group prefix and records member receipt tokens, deadlines, receive counts and attempt identity. A later message cannot pass an earlier unavailable head. Independent groups can progress concurrently; one hot group still serializes. MessageGroup partitioning selects one group per receive, up to the overall ten-message budget. Receipt handles identify the queue incarnation, purge generation and current claim. An adapter restart does not discard them. Delete settles only that exact claim; visibility changes update only its member. A stale receipt cannot delete a newer delivery. Visibility uses stored state, without a broker’s five-minute lock ceiling; normal SQS validation and retention still apply. A consumer can keep executing after expiration, so external effects must remain idempotent. The conservative batch protocol waits until all unsettled members have settled or expired before redelivery. It does not interleave a redelivery batch with still-live members. That reduces availability when visibility deadlines differ. In Queue scope, an unchanged ReceiveRequestAttemptId can replay its original set for five minutes, reset visibility and avoid incrementing the receive count. A modified or replaced claim requires a new attempt and returns an explicit unsupported result. MessageGroup scope rejects explicit attempt IDs before claiming because there is no cross-partition attempt coordinator. These are material differences from an unrestricted SQS batch/replay contract.Persistent queue management and total cost
Cloud Adapter retains a persistent PostgreSQL store for the queue catalog, tenancy and lifecycle/control state, normally shared with the Cloud Adapter deployment. Native broker or Cosmos message storage does not remove this resource. Include its allocated compute, storage, backups and selected HA costs alongside adapter and message-backend charges; an idle or serverless message backend does not imply a zero total installation floor. Backend-only curves omit these shared allocations unless their assumptions explicitly include them. This control store is distinct from the SQS-owned message database. PostgreSQL-authority FIFO composites add recoverable message bodies, receipts, deduplication and outbox state to an explicitly configured SQS message database; they do not store messages in the shared control catalog. A separate logical database and login provide data/permission separation, but still share server CPU, storage, IOPS, WAL and connection limits when hosted on the same instance. Dedicated physical server/instance capacity is a separate allocation and cost decision.Cosmos capacity and partition choice
Serverless charges consumed request units and suits idle-heavy queues. Manual provisioned throughput suits steady demand; autoscale suits varying provisioned demand. They use the same queue protocol, with different configured RU budgets and minimum charges. Changing RU capacity does not remove transaction, document-size, hot-partition or retained-storage constraints. Throttling and retry-after consume the caller’s time budget. The transactional FIFO design chooses its deduplication scope explicitly. Queue-wide dedup keeps all groups, messages, attempts and markers in one logical partition so one server-side transaction can accept a send atomically. MessageGroup scope partitions by group only when that scope is explicitly requested. It must never silently weaken queue-wide duplicate suppression. A logical partition’s 20-GB storage ceiling applies to the whole queue in Queue scope and to the busiest group in MessageGroup scope, including payload, indexes, markers, attempts, terminal evidence and cleanup lag. RU upgrades do not raise that ceiling; serverless can have a lower usable RU budget. Admission validates the actual serialized body, attributes and transaction overhead before effects. The existing article’s declared payload limit is distinct from the larger-body transactional design: the latter must fit the complete 2-MB/100-operation same-partition transaction budget. It never truncates an oversized transaction or splits one atomic acceptance into an unsafe marker-then-body sequence. Compute cost from observed RU per successful operation plus conditional conflicts, retries, count queries, empty polls and cleanup; include stored bytes and the selected capacity floor. Missing body/attribute sizes, backlog, hottest-group fraction or measured index overhead leave storage/RU fit unknown. Serverless-to-provisioned conversion affects the account and is irreversible; it requires an explicit resource decision.Transactional Cosmos FIFO and lifecycle
A bounded server-side procedure validates the partition generation, finds or replaces the dedup marker, allocates sequence and inserts the message atomically. A five-minute duplicate echoes the original IDs even after the message is deleted. TTL performs cleanup; explicit stored expiry decides deduplication and receipt eligibility. Receive conditionally claims the earliest eligible sequence, and Delete advances the group only for its exact receipt generation. This design differs from a collection of independent marker/head updates. Queue-scope attempts fit inside that same partition and use conservative ordered-batch/replay behavior. MessageGroup scope serves one group per receive, up to ten ordered members, and rejects explicit ReceiveRequestAttemptId before claims because there is no cross-partition replay coordinator. Cross-partition dead-letter transfer/redrive is unsupported; sharing a Cosmos account does not make it atomic. Queue-scope purge changes its local generation. Group-partitioned purge closes group registration, durably freezes every registered partition and only then opens the next generation. Interrupted work resumes from its saved progress and can reduce availability; success is not returned halfway. Dedup history survives purge until its original expiry. Delete permanently retires the incarnation, and recreate uses another one, so a delayed initializer, receipt or cleanup task cannot operate on the replacement queue.Deployment, security and application changes
Provision the account, database, containers, indexes and versioned bounded server procedures explicitly. Validate their actual consistency, partition layout, capacity and credentials; a data credential does not confer management permission. The adapter uses the customer’s workload identity and TLS to the configured Cosmos endpoint. Isolate tenant/account and queue identity in stored keys and authorization. Retention is checked from durable acceptance/expiry state. Cleanup cannot erase a body still needed for valid response replay. Count observations require their own supported query and can lag concurrent sends, settlement and expiry; configured capacity and cached counts are not a throughput measurement. Queues start empty. Drain each source group before cutover, keep stable dedup IDs on uncertain retries and handle per-entry batch failures. Select another backend if the application requires cross-partition atomic dead-letter moves, explicit receive-attempt replay in group-partitioned mode, or retained bytes above the authoritative partition’s limit. Increasing RU or consumer count cannot remove these restrictions.Example monthly charges
This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. How Tensor9 estimates costs explains the method and what the estimates include.SQS FIFO · SQS request billing units
Feature: SQS FIFO. Estimated monthly service charges by SQS request billing units. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: East US; currency: USD.- 1-KiB messages, unbatched send/receive/delete; actual batch and delivery assumptions stay visible. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
- Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → East US, USD/month.
- Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
- Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
- Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve’s workload note.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Azure Cosmos DB provisioned throughput bills 100-RU/s blocks per hour and stored GB-months; operations within the provisioned RU/s have no separate charge. Blocks are sized from the family’s reads at 1 RU and writes at 5.5 RU (1 KB items, no extra indexing) at full utilization after the planning peak factor, with the 400 RU/s smallest manual allocation as the floor (USD 23.36/month). Larger messages, indexing and query-based receives raise the RU charge; autoscale (USD 0.012 per 100 RU/s-hour) and serverless (USD 0.25 per million RUs) are not selected.
- AWS Price List API, AWSQueueService offer: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSQueueService/current/us-east-1/index.json
- Azure Retail Prices API: https://prices.azure.com/api/retail/prices
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
plan-4f4f008a52eb766d518aa4f34d3302fdb02b1a67 / 2026-10-22.planning.2. Curve: workload-1.
Sources: AWS Price List API, AWSQueueService offer, Azure Retail Prices API.
SQS FIFO → Azure Cosmos DB (queue): Authored native-usage planning example. Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.
Scenario source region: us-east-1. Scenario target region: East US. Currency: USD.
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
- Translated reads: 0 operations.
- Translated writes: 0 operations.
- Translated resident physical data: 0 GiB-month.
- Native provider operations: 0 operations.
- Published payload: 0 GiB.
- Delivered payload: 0 GiB.
- Allocated execution CPU: 0 vCPU-hour.
- Allocated execution RAM: 0 GiB-hour.
- Independent resource allocation: 0 resource-hour.
- Independent inventory: 0 resource-month.
- Input tokens: 0 tokens.
- Output tokens: 0 tokens.
- Billable network: 0 GiB.
- Dependent object sink retained data: 0 GiB-month.
- Dependent object sink writes: 0 writes.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Azure Cosmos DB provisioned throughput bills 100-RU/s blocks per hour and stored GB-months; operations within the provisioned RU/s have no separate charge. Blocks are sized from the family’s reads at 1 RU and writes at 5.5 RU (1 KB items, no extra indexing) at full utilization after the planning peak factor, with the 400 RU/s smallest manual allocation as the floor (USD 23.36/month). Larger messages, indexing and query-based receives raise the RU charge; autoscale (USD 0.012 per 100 RU/s-hour) and serverless (USD 0.25 per million RUs) are not selected.
plan-4f4f008a52eb766d518aa4f34d3302fdb02b1a67 / 2026-10-22.planning.2. Scenario: planning-example.
Sources: AWS Price List API, AWSQueueService offer, Azure Retail Prices API.
PostgreSQL Flexible Server
PostgreSQL hosting
Microsoft operates PostgreSQL Flexible Server, including zone-redundant HA and point-in-time recovery backups. The adapter uses short-lived Microsoft Entra tokens as database passwords. Queue data stays outside the customer’s Kubernetes cluster and survives its rebuild. One server and database hold all queues for the deployment, sharing capacity and maintenance; the default server size is fixed because SQS supplies no source instance size. Tensor9 operates the queue schema and adapter. Queues start empty; existing SQS messages are not migrated. Drain each message group before cutover to preserve order.Persistent queue management and total cost
Cloud Adapter retains a persistent PostgreSQL store for the queue catalog, tenancy and lifecycle/control state, normally shared with the Cloud Adapter deployment. Native broker or Cosmos message storage does not remove this resource. Include its allocated compute, storage, backups and selected HA costs alongside adapter and message-backend charges; an idle or serverless message backend does not imply a zero total installation floor. Backend-only curves omit these shared allocations unless their assumptions explicitly include them. This control store is distinct from the SQS-owned message database. PostgreSQL-authority FIFO composites add recoverable message bodies, receipts, deduplication and outbox state to an explicitly configured SQS message database; they do not store messages in the shared control catalog. A separate logical database and login provide data/permission separation, but still share server CPU, storage, IOPS, WAL and connection limits when hosted on the same instance. Dedicated physical server/instance capacity is a separate allocation and cost decision.Database placement and recovery
Azure Database for PostgreSQL Flexible Server is the durable queue database in your Azure subscription. The adapter connects over TLS using short-lived Microsoft Entra database credentials. Microsoft operates the server; choose the required HA and backup configuration explicitly. AKS replacement does not replace the database. Server failover can interrupt connections and leave an in-progress commit’s response uncertain, so consumers retain their ordinary redelivery and retry handling.Capacity and queue workload
The default shared message database holds multiple queues, each with its own table. Dedicated physical server/instance capacity isolates compute and I/O from other server workloads; a separate logical database alone does not. HA changes recovery, commit latency and price rather than FIFO semantics. Neither choice creates an unlimited queue service. Size connection pools, storage, IOPS and WAL for accepted sends, receives, deletes, visibility changes, retries and cleanup together. Long polls wait outside database transactions. The single-message receive mechanism below permits one message in flight per group. If a group takes T seconds from receive to settlement, its useful completion rate is bounded by roughly 1/T, even when other groups are idle. A larger MaxNumberOfMessages can collect heads from multiple groups; it does not create a ten-message pipeline within one group. Adding consumers or database CPU does not remove that serialization. Compare the separate ordered-batch design before selecting a workload that depends on within-group batching. Requested live counts scan the message population even for a single requested counter. Frequent depth polling over a large backlog competes for database I/O and pool capacity; receipt classification can change index/heap work. Price those queries separately from sends and completed message cycles. A fall in depth can reflect purge, expiry or dead-letter transfer rather than application completion. The portable Standard-queue benchmark does not establish the capacity of this host, its HA configuration or a FIFO workload. Payload sizes, active-group skew, settlement time, backlog growth and matched native measurements determine whether a proposed size fits. Missing measurements leave capacity unknown.Retries, batches and application changes
The application keeps its SQS SDK and uses the adapter’s configured endpoint and authentication. Backend IAM, database schema permissions and TLS identity belong to the deployment; an AWS ARN or policy is not automatically a target-cloud authorization grant. Scope identities to the customer resources and keep rotated credentials out of message bodies and receipt handles. A batch response reports each entry separately. Retry only failed entries whose outcome is known; a request timeout can follow a committed send or delete. Keep the same effective deduplication ID on uncertain retries. Duplicate enqueue suppression does not make consumer side effects exactly once. SDK retries and adapter retries share one bounded deadline, with backoff for provider throttling. An expired observer deadline does not prove a still-running native operation was cancelled. Visibility expiration permits another delivery while an earlier worker can still be executing. Consumers use idempotent writes, choose a visibility duration that covers normal processing and handle stale receipt errors. Retention can expire a message in flight. Queues start empty: drain the source before cutover, group by group. Queue recreation and purge must invalidate old claims independently of public names; data cleanup can continue after logical retirement. Database or broker backup is a resource recovery mechanism, not an automatic replay of application side effects.PostgreSQL queue behavior
Your application keeps its SQS SDK and uses the authenticated Cloud Adapter endpoint configured for the install. The adapter performsSendMessage and ReceiveMessage in the SQS-owned PostgreSQL message database and returns SQS responses, error codes and MD5 checksums. Its message-data login is separate from other services and the shared control catalog.
Each queue is a PostgreSQL table with one row per message. Sending, receiving, deleting, delays, visibility, dead-letter delivery and message counts all work on those rows. FIFO queues add ordering by message group, per-group sequence numbers and duplicate detection. Consumers can still receive a message more than once.
The application keeps its SQS SDK. The adapter stores each queue in a PostgreSQL table.
Architecture
The adapter keeps all queue state in PostgreSQL, including messages and receipt handles, so adapter instances can restart or scale out without losing track of in-flight messages. On Cloud SQL and Azure Flexible Server it signs in with short-lived Cloud SQL IAM or Microsoft Entra tokens used as database passwords, so no static secret is stored. When the stack is deployed, Tensor9 creates one database per Cloud Adapter deployment and one table per declared queue. Each row holds the message body and attributes, its message group, its visibility time, its receipt handle, its receive count and the time it was sent. A FIFO queue orders messages within each message group; each row’s arrival position gives its sequence number. A dead-letter queue is another queue table, and a background task deletes messages older than the queue’s retention period. CloudNativePG, Cloud SQL for PostgreSQL, Azure Flexible Server and Scaleway use the same adapter code and tables. They differ in where the data lives: the managed servers run outside your Kubernetes cluster, while CloudNativePG runs inside it. See the rebuild limitation below.Each queue, including each dead-letter queue, is a PostgreSQL table. The same adapter runs on every supported PostgreSQL host.
Receiving messages
One database step selects messages whose visibility timeout has passed, oldest first, up to the requested batch size. In the same step it gives each a new receipt handle, hides it for the visibility timeout, adds one to its receive count and returns it. Messages another receiver is taking at that moment are skipped. FIFO queues return the next eligible message in each group, keeping one in flight per group. When the visibility timeout passes, the message can be delivered again; that does not stop a worker still processing the earlier copy.ApproximateReceiveCount is the actual number of receives, not an estimate. The MD5 checksums of the body and attributes are recomputed, so your SDK’s checks pass. DelaySeconds sets when a message first becomes visible. Long polling waits up to WaitTimeSeconds (at most 20 seconds) and returns as soon as a message is available. SendMessageBatch inserts all entries at once and reports a result for each entry. Message bodies are stored in the queue table.
Two receivers never get the same message at the same time. ApproximateReceiveCount is the actual receive count.
Receipt handles & visibility
Each receive saves a new receipt handle with the message.DeleteMessage and ChangeMessageVisibility find the message by that handle, including after an adapter restart or through another adapter instance.
A delete or visibility change whose handle matches no message returns ReceiptHandleIsInvalid. That includes a message already deleted, or received again under a newer handle. The visibility timeout defaults to 30 seconds. ChangeMessageVisibility can extend it with no lock-duration maximum, and zero makes the message available again immediately. Retention can delete a message while it is in flight.
Receipt handles are saved with messages, so they still work after an adapter restart. Visibility has no lock-duration limit.
Dead-letter & retention
When source and DLQ belong to the same supported SQS-owned message database transaction, receive moves messages atmaxReceiveCount atomically with claiming the rest. Both changes commit or neither does. Cross-database/store transfers are unsupported: sharing a provider, physical server or control log is not a shared message transaction, and no other service’s tables are used. The DLQ retains ordinary queue operations and cleanup. A FIFO move creates a new message in the DLQ, with a new MessageId, a receive count of zero and a new send time.
A background task deletes messages sent longer ago than the queue’s retention period, including messages in flight; receiving does not reset that time. The retention period defaults to four days and is kept between 60 seconds and 14 days, so a missing or too-short value cannot delete new messages straight away. One worker per database removes expired messages in batches, pauses during database maintenance, and continues if one queue fails. Limits on rows per pass and time per batch cap the load.
Atomic DLQ moves require the same supported SQS-owned database transaction. Cross-store moves are unsupported. Retention cleanup removes aged messages.
FIFO ordering & dedup
A FIFO queue stores each message’sMessageGroupId and orders delivery within each group. A receive returns only the oldest message of each group that has nothing in flight (no message in that group is currently received and still hidden). Because arrival positions only increase, that is always the group’s next message, and exactly one message is in flight per group at a time. Groups are independent, so different receivers can process different groups at once, coordinated only by PostgreSQL. When a message’s visibility timeout passes, it is first in its group again, so a redelivery stays in sequence.
Each FIFO send requires MessageGroupId and returns a SequenceNumber: the message’s arrival position as a 20-digit, zero-padded number.
Deduplication markers live in a separate PostgreSQL table keyed by queue and deduplication ID. An explicit MessageDeduplicationId takes precedence; otherwise, on a queue with content-based deduplication, the key is the SHA-256 of the body, excluding attributes. The message insert and deduplication marker are part of one transaction. A duplicate within 5 minutes saves no new message and returns the original MessageId and SequenceNumber. Marker retention is independent of message retention, so receiving or deleting the original does not shorten the deduplication window.
While a message is in flight, no other message from its group is delivered until it is deleted or its visibility timeout passes. That does not stop a timed-out worker from finishing a message it already received, so consumers must make repeated processing safe.
FIFO receives deliver one message per group at a time. Sends return a SequenceNumber, and repeated sends within 5 minutes are suppressed, matched by an explicit ID or, with content-based deduplication, a body hash.
Limitations
Where SQS and the PostgreSQL adapter differ- Throughput behaves differently: one PostgreSQL server serves every queue. All of a Cloud Adapter deployment’s queues share one server, so its capacity bounds peak throughput and a heavy queue can affect the others. In Tensor9’s round-trip test of a moderate-rate Standard queue, the adapter matched SQS throughput (about 300 vs 286 ops/s) with a lower p99 (140 ms vs 172 ms) but a slower median (p50 24 ms vs 15 ms). That is not a measured ceiling, and it does not cover FIFO queues or every host.
- Recovery follows the database placement. The managed database is outside the Cloud Adapter deployment cluster, so replacing that cluster does not replace the queue data. Database availability and recovery still depend on the selected server, HA and backup configuration.
- Messages are limited to 256 KiB by default. The adapter’s default limit is 262144 bytes, while native SQS now accepts up to 1 MiB. Sends are checked against the queue’s declared limit.
- FIFO send deduplication lasts 5 minutes. A duplicate send within that window returns the original IDs. Reusing an ID after the window can create a new message. Consumer redelivery remains possible even within the window.
- Stale receipt handles behave differently: they return an error.
DeleteMessageandChangeMessageVisibilityreturnReceiptHandleIsInvalidwhen no message matches the handle. - Retention behaves differently: expired messages are removed periodically. An expired message can remain until the next cleanup pass. Retention is kept between 60 seconds and 14 days; a too-short value is raised to 60 seconds so that new messages are not deleted.
- Counts observe queue state, not application completion. Requested message counts read the message database: eligible messages are visible, future-visible messages with a receipt are in flight, and future-visible messages without a receipt are initially delayed. These categories share one query snapshot and can change immediately afterward. Metadata-only reads do not require a message-table count. An unavailable requested count returns an explicit unsupported result rather than zero. Purge, expiry and dead-letter movement can reduce depth without completing the application’s work.
- Queue creation behaves differently: queues are created when the stack is deployed. Tensor9 creates the database and each queue’s table, and its dead-letter table, at deploy time.
CreateQueue,DeleteQueueandSetQueueAttributesact on those tables. Switching a queue between Standard and FIFO is rejected, because it would replace the queue.
Other considerations
- Moving from AWS. The database and queue tables start empty, and existing SQS messages are not migrated. Drain each group before switching it, to preserve order.
- Removing queues. Each queue is created in one step, so a crash never leaves a half-created queue. When a queue is removed from the stack, Tensor9 deletes only queues it created; any other queue is detached and left in place. A queue that still holds messages is not deleted unless deletion is forced.
- Who operates what. On the managed hosts, the provider operates the database’s durability, backups and high availability, and Tensor9 operates the adapter. On CloudNativePG, Tensor9 operates the database inside your cluster.
Example monthly charges
This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. How Tensor9 estimates costs explains the method and what the estimates include.SQS FIFO · SQS request billing units
Feature: SQS FIFO. Estimated monthly service charges by SQS request billing units. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: eastus; currency: USD.- 1-KiB messages, unbatched send/receive/delete; actual batch and delivery assumptions stay visible. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
- Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → eastus, USD/month.
- Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
- Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
- Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve’s workload note.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Azure Database for PostgreSQL Flexible Server bills vCores with a fixed memory ratio per series; the vCPU and memory rates decompose the General Purpose and Memory Optimized v5 prices. High availability bills the standby’s compute and storage as a second copy. The minimum is the smallest Burstable server, which does not support high availability; the smallest General Purpose server (2 vCores) costs USD 133.62 per month. Additional IOPS, backup storage and reserved capacity are not selected.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: E96ds_v5 has 96 vCores and 672 GiB (https://learn.microsoft.com/en-us/azure/postgresql/compute-storage/concepts-compute); Premium SSD storage holds up to 32,767 GiB (https://learn.microsoft.com/en-us/azure/postgresql/compute-storage/concepts-storage).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
- AWS Price List API, AWSQueueService offer: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSQueueService/current/us-east-1/index.json
- Azure Retail Prices API: https://prices.azure.com/api/retail/prices
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
plan-d6e6756733e57b05fe1084c81427de33e78217f0 / 2026-10-22.planning.2. Curve: workload-1.
Sources: AWS Price List API, AWSQueueService offer, Azure Retail Prices API.
SQS FIFO → PostgreSQL Flexible Server: Authored native-usage planning example. Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.
Scenario source region: us-east-1. Scenario target region: eastus. Currency: USD.
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
- Translated reads: 0 operations.
- Translated writes: 0 operations.
- Translated resident physical data: 0 GiB-month.
- Native provider operations: 0 operations.
- Published payload: 0 GiB.
- Delivered payload: 0 GiB.
- Allocated execution CPU: 0 vCPU-hour.
- Allocated execution RAM: 0 GiB-hour.
- Independent resource allocation: 0 resource-hour.
- Independent inventory: 0 resource-month.
- Input tokens: 0 tokens.
- Output tokens: 0 tokens.
- Billable network: 0 GiB.
- Dependent object sink retained data: 0 GiB-month.
- Dependent object sink writes: 0 writes.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Azure Database for PostgreSQL Flexible Server bills vCores with a fixed memory ratio per series; the vCPU and memory rates decompose the General Purpose and Memory Optimized v5 prices. High availability bills the standby’s compute and storage as a second copy. The minimum is the smallest Burstable server, which does not support high availability; the smallest General Purpose server (2 vCores) costs USD 133.62 per month. Additional IOPS, backup storage and reserved capacity are not selected.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: E96ds_v5 has 96 vCores and 672 GiB (https://learn.microsoft.com/en-us/azure/postgresql/compute-storage/concepts-compute); Premium SSD storage holds up to 32,767 GiB (https://learn.microsoft.com/en-us/azure/postgresql/compute-storage/concepts-storage).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
plan-d6e6756733e57b05fe1084c81427de33e78217f0 / 2026-10-22.planning.2. Scenario: planning-example.
Sources: AWS Price List API, AWSQueueService offer, Azure Retail Prices API.
On Google Cloud
Cloud SQL for PostgreSQL
PostgreSQL hosting
Google operates Cloud SQL for PostgreSQL, including database backups and HA. The adapter uses short-lived Cloud SQL IAM tokens as database passwords, without an Auth Proxy or static password. Queue data stays outside the customer’s Kubernetes cluster and survives its rebuild. Tensor9 operates the queue schema and adapter. Queues start empty; existing SQS messages are not migrated. Drain each message group before cutover to preserve order.Persistent queue management and total cost
Cloud Adapter retains a persistent PostgreSQL store for the queue catalog, tenancy and lifecycle/control state, normally shared with the Cloud Adapter deployment. Native broker or Cosmos message storage does not remove this resource. Include its allocated compute, storage, backups and selected HA costs alongside adapter and message-backend charges; an idle or serverless message backend does not imply a zero total installation floor. Backend-only curves omit these shared allocations unless their assumptions explicitly include them. This control store is distinct from the SQS-owned message database. PostgreSQL-authority FIFO composites add recoverable message bodies, receipts, deduplication and outbox state to an explicitly configured SQS message database; they do not store messages in the shared control catalog. A separate logical database and login provide data/permission separation, but still share server CPU, storage, IOPS, WAL and connection limits when hosted on the same instance. Dedicated physical server/instance capacity is a separate allocation and cost decision.Database placement and recovery
Cloud SQL is the durable queue database in your Google Cloud project. The adapter connects over TLS using short-lived IAM database credentials; Google operates the database. Zonal and high-availability configurations have different failure and maintenance behavior. Database backups and recovery policy belong to the selected configuration; they do not make every acknowledged queue operation immune to every database failure. GKE replacement does not replace this external database. Keep its identity and queue schema when rebuilding the application cluster.Capacity and queue workload
The default shared message database holds multiple queues, each with its own table. Dedicated physical server/instance capacity isolates compute and I/O from other server workloads; a separate logical database alone does not. HA changes recovery, commit latency and price rather than FIFO semantics. Neither choice creates an unlimited queue service. Size connection pools, storage, IOPS and WAL for accepted sends, receives, deletes, visibility changes, retries and cleanup together. Long polls wait outside database transactions. The single-message receive mechanism below permits one message in flight per group. If a group takes T seconds from receive to settlement, its useful completion rate is bounded by roughly 1/T, even when other groups are idle. A larger MaxNumberOfMessages can collect heads from multiple groups; it does not create a ten-message pipeline within one group. Adding consumers or database CPU does not remove that serialization. Compare the separate ordered-batch design before selecting a workload that depends on within-group batching. Requested live counts scan the message population even for a single requested counter. Frequent depth polling over a large backlog competes for database I/O and pool capacity; receipt classification can change index/heap work. Price those queries separately from sends and completed message cycles. A fall in depth can reflect purge, expiry or dead-letter transfer rather than application completion. The portable Standard-queue benchmark does not establish the capacity of this host, its HA configuration or a FIFO workload. Payload sizes, active-group skew, settlement time, backlog growth and matched native measurements determine whether a proposed size fits. Missing measurements leave capacity unknown.Retries, batches and application changes
The application keeps its SQS SDK and uses the adapter’s configured endpoint and authentication. Backend IAM, database schema permissions and TLS identity belong to the deployment; an AWS ARN or policy is not automatically a target-cloud authorization grant. Scope identities to the customer resources and keep rotated credentials out of message bodies and receipt handles. A batch response reports each entry separately. Retry only failed entries whose outcome is known; a request timeout can follow a committed send or delete. Keep the same effective deduplication ID on uncertain retries. Duplicate enqueue suppression does not make consumer side effects exactly once. SDK retries and adapter retries share one bounded deadline, with backoff for provider throttling. An expired observer deadline does not prove a still-running native operation was cancelled. Visibility expiration permits another delivery while an earlier worker can still be executing. Consumers use idempotent writes, choose a visibility duration that covers normal processing and handle stale receipt errors. Retention can expire a message in flight. Queues start empty: drain the source before cutover, group by group. Queue recreation and purge must invalidate old claims independently of public names; data cleanup can continue after logical retirement. Database or broker backup is a resource recovery mechanism, not an automatic replay of application side effects.PostgreSQL queue behavior
Your application keeps its SQS SDK and uses the authenticated Cloud Adapter endpoint configured for the install. The adapter performsSendMessage and ReceiveMessage in the SQS-owned PostgreSQL message database and returns SQS responses, error codes and MD5 checksums. Its message-data login is separate from other services and the shared control catalog.
Each queue is a PostgreSQL table with one row per message. Sending, receiving, deleting, delays, visibility, dead-letter delivery and message counts all work on those rows. FIFO queues add ordering by message group, per-group sequence numbers and duplicate detection. Consumers can still receive a message more than once.
The application keeps its SQS SDK. The adapter stores each queue in a PostgreSQL table.
Architecture
The adapter keeps all queue state in PostgreSQL, including messages and receipt handles, so adapter instances can restart or scale out without losing track of in-flight messages. On Cloud SQL and Azure Flexible Server it signs in with short-lived Cloud SQL IAM or Microsoft Entra tokens used as database passwords, so no static secret is stored. When the stack is deployed, Tensor9 creates one database per Cloud Adapter deployment and one table per declared queue. Each row holds the message body and attributes, its message group, its visibility time, its receipt handle, its receive count and the time it was sent. A FIFO queue orders messages within each message group; each row’s arrival position gives its sequence number. A dead-letter queue is another queue table, and a background task deletes messages older than the queue’s retention period. CloudNativePG, Cloud SQL for PostgreSQL, Azure Flexible Server and Scaleway use the same adapter code and tables. They differ in where the data lives: the managed servers run outside your Kubernetes cluster, while CloudNativePG runs inside it. See the rebuild limitation below.Each queue, including each dead-letter queue, is a PostgreSQL table. The same adapter runs on every supported PostgreSQL host.
Receiving messages
One database step selects messages whose visibility timeout has passed, oldest first, up to the requested batch size. In the same step it gives each a new receipt handle, hides it for the visibility timeout, adds one to its receive count and returns it. Messages another receiver is taking at that moment are skipped. FIFO queues return the next eligible message in each group, keeping one in flight per group. When the visibility timeout passes, the message can be delivered again; that does not stop a worker still processing the earlier copy.ApproximateReceiveCount is the actual number of receives, not an estimate. The MD5 checksums of the body and attributes are recomputed, so your SDK’s checks pass. DelaySeconds sets when a message first becomes visible. Long polling waits up to WaitTimeSeconds (at most 20 seconds) and returns as soon as a message is available. SendMessageBatch inserts all entries at once and reports a result for each entry. Message bodies are stored in the queue table.
Two receivers never get the same message at the same time. ApproximateReceiveCount is the actual receive count.
Receipt handles & visibility
Each receive saves a new receipt handle with the message.DeleteMessage and ChangeMessageVisibility find the message by that handle, including after an adapter restart or through another adapter instance.
A delete or visibility change whose handle matches no message returns ReceiptHandleIsInvalid. That includes a message already deleted, or received again under a newer handle. The visibility timeout defaults to 30 seconds. ChangeMessageVisibility can extend it with no lock-duration maximum, and zero makes the message available again immediately. Retention can delete a message while it is in flight.
Receipt handles are saved with messages, so they still work after an adapter restart. Visibility has no lock-duration limit.
Dead-letter & retention
When source and DLQ belong to the same supported SQS-owned message database transaction, receive moves messages atmaxReceiveCount atomically with claiming the rest. Both changes commit or neither does. Cross-database/store transfers are unsupported: sharing a provider, physical server or control log is not a shared message transaction, and no other service’s tables are used. The DLQ retains ordinary queue operations and cleanup. A FIFO move creates a new message in the DLQ, with a new MessageId, a receive count of zero and a new send time.
A background task deletes messages sent longer ago than the queue’s retention period, including messages in flight; receiving does not reset that time. The retention period defaults to four days and is kept between 60 seconds and 14 days, so a missing or too-short value cannot delete new messages straight away. One worker per database removes expired messages in batches, pauses during database maintenance, and continues if one queue fails. Limits on rows per pass and time per batch cap the load.
Atomic DLQ moves require the same supported SQS-owned database transaction. Cross-store moves are unsupported. Retention cleanup removes aged messages.
FIFO ordering & dedup
A FIFO queue stores each message’sMessageGroupId and orders delivery within each group. A receive returns only the oldest message of each group that has nothing in flight (no message in that group is currently received and still hidden). Because arrival positions only increase, that is always the group’s next message, and exactly one message is in flight per group at a time. Groups are independent, so different receivers can process different groups at once, coordinated only by PostgreSQL. When a message’s visibility timeout passes, it is first in its group again, so a redelivery stays in sequence.
Each FIFO send requires MessageGroupId and returns a SequenceNumber: the message’s arrival position as a 20-digit, zero-padded number.
Deduplication markers live in a separate PostgreSQL table keyed by queue and deduplication ID. An explicit MessageDeduplicationId takes precedence; otherwise, on a queue with content-based deduplication, the key is the SHA-256 of the body, excluding attributes. The message insert and deduplication marker are part of one transaction. A duplicate within 5 minutes saves no new message and returns the original MessageId and SequenceNumber. Marker retention is independent of message retention, so receiving or deleting the original does not shorten the deduplication window.
While a message is in flight, no other message from its group is delivered until it is deleted or its visibility timeout passes. That does not stop a timed-out worker from finishing a message it already received, so consumers must make repeated processing safe.
FIFO receives deliver one message per group at a time. Sends return a SequenceNumber, and repeated sends within 5 minutes are suppressed, matched by an explicit ID or, with content-based deduplication, a body hash.
Limitations
Where SQS and the PostgreSQL adapter differ- Throughput behaves differently: one PostgreSQL server serves every queue. All of a Cloud Adapter deployment’s queues share one server, so its capacity bounds peak throughput and a heavy queue can affect the others. In Tensor9’s round-trip test of a moderate-rate Standard queue, the adapter matched SQS throughput (about 300 vs 286 ops/s) with a lower p99 (140 ms vs 172 ms) but a slower median (p50 24 ms vs 15 ms). That is not a measured ceiling, and it does not cover FIFO queues or every host.
- Recovery follows the database placement. The managed database is outside the Cloud Adapter deployment cluster, so replacing that cluster does not replace the queue data. Database availability and recovery still depend on the selected server, HA and backup configuration.
- Messages are limited to 256 KiB by default. The adapter’s default limit is 262144 bytes, while native SQS now accepts up to 1 MiB. Sends are checked against the queue’s declared limit.
- FIFO send deduplication lasts 5 minutes. A duplicate send within that window returns the original IDs. Reusing an ID after the window can create a new message. Consumer redelivery remains possible even within the window.
- Stale receipt handles behave differently: they return an error.
DeleteMessageandChangeMessageVisibilityreturnReceiptHandleIsInvalidwhen no message matches the handle. - Retention behaves differently: expired messages are removed periodically. An expired message can remain until the next cleanup pass. Retention is kept between 60 seconds and 14 days; a too-short value is raised to 60 seconds so that new messages are not deleted.
- Counts observe queue state, not application completion. Requested message counts read the message database: eligible messages are visible, future-visible messages with a receipt are in flight, and future-visible messages without a receipt are initially delayed. These categories share one query snapshot and can change immediately afterward. Metadata-only reads do not require a message-table count. An unavailable requested count returns an explicit unsupported result rather than zero. Purge, expiry and dead-letter movement can reduce depth without completing the application’s work.
- Queue creation behaves differently: queues are created when the stack is deployed. Tensor9 creates the database and each queue’s table, and its dead-letter table, at deploy time.
CreateQueue,DeleteQueueandSetQueueAttributesact on those tables. Switching a queue between Standard and FIFO is rejected, because it would replace the queue.
Other considerations
- Moving from AWS. The database and queue tables start empty, and existing SQS messages are not migrated. Drain each group before switching it, to preserve order.
- Removing queues. Each queue is created in one step, so a crash never leaves a half-created queue. When a queue is removed from the stack, Tensor9 deletes only queues it created; any other queue is detached and left in place. A queue that still holds messages is not deleted unless deletion is forced.
- Who operates what. On the managed hosts, the provider operates the database’s durability, backups and high availability, and Tensor9 operates the adapter. On CloudNativePG, Tensor9 operates the database inside your cluster.
Google Cloud queue designs
FIFO needs durable group order, deduplication results, user receipts and lifecycle generations. The following designs have different storage owners and bills. Choosing one is an explicit resource/configuration decision; the adapter does not move a running queue between them automatically. | Design | Where bodies and queue state live | Workload consequence | | --- | --- | --- | | Cloud SQL PostgreSQL | Transactional bodies, receipts and dedup | Shared/dedicated capacity; zonal/HA placement | | Firestore | Transactional manifests, binary chunks and claims | Idle-heavy/many-group traffic; hot-group contention and operation/index charges | | Regional Spanner | Serializable queue transactions and binary chunks | Aggregate distributed load; capacity floor and hot-group serialization | | Pub/Sub full-body FIFO + PostgreSQL | Recoverable body in SQL; another body copy traverses Pub/Sub | Two-service cost; first delivery waits for broker observation; per-key payload limit | | PostgreSQL FIFO + Pub/Sub wakeups | Bodies/user state in SQL; broker carries ready hints | Scans repair lost hints; compare with LISTEN/NOTIFY | Firestore: a message manifest and its immutable binary chunks commit together. A 1-MiB body uses four 256-KiB chunks, avoiding Firestore’s per-document limit without introducing a Cloud Storage bucket. Attributes, transaction overhead and indexes must also fit the complete request. Candidate queries are hints; the transaction checks queue generation and claims the group. Chunk cleanup waits until no valid delivery/replay needs the body. Spanner: distributed group keys spread independent work. A read-write transaction checks lifecycle state, deduplication and group ownership before accepting or claiming a message. A read-only scan never owns a delivery. Unknown commit results are resolved from operation identity and durable state. Regional placement is explicit; this design makes no automatic multi-region recovery or measured throughput claim. Full-body Pub/Sub FIFO: Send commits body, group sequence, dedup result and publication intent in PostgreSQL. A publisher sends the body with stable logical identity and digest. A subscriber verifies the existing authority row and records broker observation before acknowledging the physical copy. Only observed eligible group heads reach SQS consumers. Broker acknowledgement is not SQS DeleteMessage: PostgreSQL retains the body and user claim. An outage before observation blocks first delivery and can consume retention time. Pub/Sub’s 1 MB/s ordering-key publish limit applies to bodies, attributes and transport-envelope bytes; more consumers do not remove it. Wakeups: Send commits the same database state but publishes only queue/group readiness. Receive can claim from PostgreSQL without a notification, using bounded repair scans. Duplicate or reordered notifications cannot allocate another message or advance a group. A broker outage can increase discovery latency, while database availability still determines message service. The notification byte limit is not a payload throughput estimate. The transactional designs retain queue incarnation and purge generation with every message, receipt and pending publication. A late publisher cannot recreate a deleted body or enter a replacement queue. Firestore, Spanner and SQL-assisted FIFO transport designs use the separate ordered-batch protocol, rather than direct PostgreSQL’s one-head-per-group mechanism. They return a contiguous group prefix up to the overall ten-message budget, but conservatively wait for all remaining members to settle or expire before redelivery. This is a restriction when individual members have different visibility deadlines. Valid five-minute ReceiveRequestAttemptId replays return the same unchanged set and refresh visibility without another receive-count increment; modified claims return an explicit unsupported result requiring a new attempt. These designs do not establish full AWS batch/replay equivalence. Atomic dead-letter moves require source and target in the same supported transaction. Cross-store moves/redrive are unsupported. Moving a blocked FIFO head to a dead-letter queue permits later messages to proceed and changes the original business sequence; decide whether that is appropriate for the application.Example monthly charges
This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. How Tensor9 estimates costs explains the method and what the estimates include. Native or deployment mapping. FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability. Cost estimates describe the selected service resources; operation coverage remains separate.SQS FIFO · SQS request billing units
Feature: SQS FIFO. Estimated monthly service charges by SQS request billing units. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: us-central1; currency: USD.- 1-KiB messages, unbatched send/receive/delete; actual batch and delivery assumptions stay visible. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
- Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → us-central1, USD/month.
- Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
- Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
- Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve’s workload note.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Native/deployment comparison scope: FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Cloud SQL Enterprise edition (PostgreSQL) publishes separate vCPU, memory and SSD prices for zonal instances; a high-availability (regional) instance bills exactly twice each, which the standby copy reproduces. Enterprise Plus, committed-use discounts, backups (USD 0.08 per GiB-month) and idle IPv4 addresses (0.01 per hour) are not selected.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: Cloud SQL Enterprise allows 1-96 vCPUs at 0.9-6.5 GB per vCPU and up to 64 TB with a dedicated vCPU (https://docs.cloud.google.com/sql/docs/postgres/instance-settings).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
- AWS Price List API, AWSQueueService offer: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSQueueService/current/us-east-1/index.json
- Cloud SQL pricing: https://cloud.google.com/sql/pricing
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
plan-c35b94f39c83dfc6e65b2063cdc3c7857cb28524 / 2026-10-22.planning.2. Curve: workload-1.
Sources: AWS Price List API, AWSQueueService offer, Cloud SQL pricing.
SQS FIFO → Cloud SQL for PostgreSQL: Authored native-usage planning example. Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.
Scenario source region: us-east-1. Scenario target region: us-central1. Currency: USD.
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
- Translated reads: 0 operations.
- Translated writes: 0 operations.
- Translated resident physical data: 0 GiB-month.
- Native provider operations: 0 operations.
- Published payload: 0 GiB.
- Delivered payload: 0 GiB.
- Allocated execution CPU: 0 vCPU-hour.
- Allocated execution RAM: 0 GiB-hour.
- Independent resource allocation: 0 resource-hour.
- Independent inventory: 0 resource-month.
- Input tokens: 0 tokens.
- Output tokens: 0 tokens.
- Billable network: 0 GiB.
- Dependent object sink retained data: 0 GiB-month.
- Dependent object sink writes: 0 writes.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Native/deployment comparison scope: FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Cloud SQL Enterprise edition (PostgreSQL) publishes separate vCPU, memory and SSD prices for zonal instances; a high-availability (regional) instance bills exactly twice each, which the standby copy reproduces. Enterprise Plus, committed-use discounts, backups (USD 0.08 per GiB-month) and idle IPv4 addresses (0.01 per hour) are not selected.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: Cloud SQL Enterprise allows 1-96 vCPUs at 0.9-6.5 GB per vCPU and up to 64 TB with a dedicated vCPU (https://docs.cloud.google.com/sql/docs/postgres/instance-settings).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
plan-c35b94f39c83dfc6e65b2063cdc3c7857cb28524 / 2026-10-22.planning.2. Scenario: planning-example.
Sources: AWS Price List API, AWSQueueService offer, Cloud SQL pricing.
On Scaleway
Scaleway Managed Database for PostgreSQL
PostgreSQL hosting
Scaleway operates the managed PostgreSQL instance outside the customer’s Kubernetes cluster. Tensor9 operates the adapter and queue schema. Queue data survives a Kubernetes cluster rebuild; configure the managed database credentials for the adapter. Tensor9 operates the queue schema and adapter. Queues start empty; existing SQS messages are not migrated. Drain each message group before cutover to preserve order.Persistent queue management and total cost
Cloud Adapter retains a persistent PostgreSQL store for the queue catalog, tenancy and lifecycle/control state, normally shared with the Cloud Adapter deployment. Native broker or Cosmos message storage does not remove this resource. Include its allocated compute, storage, backups and selected HA costs alongside adapter and message-backend charges; an idle or serverless message backend does not imply a zero total installation floor. Backend-only curves omit these shared allocations unless their assumptions explicitly include them. This control store is distinct from the SQS-owned message database. PostgreSQL-authority FIFO composites add recoverable message bodies, receipts, deduplication and outbox state to an explicitly configured SQS message database; they do not store messages in the shared control catalog. A separate logical database and login provide data/permission separation, but still share server CPU, storage, IOPS, WAL and connection limits when hosted on the same instance. Dedicated physical server/instance capacity is a separate allocation and cost decision.Database placement and recovery
Scaleway’s managed PostgreSQL database keeps the queues outside the application cluster. Scaleway operates the server; configure the adapter’s database credentials and network access. Database capacity, availability and backups follow the selected managed instance configuration, rather than the application cluster’s lifecycle.Capacity and queue workload
The default shared message database holds multiple queues, each with its own table. Dedicated physical server/instance capacity isolates compute and I/O from other server workloads; a separate logical database alone does not. HA changes recovery, commit latency and price rather than FIFO semantics. Neither choice creates an unlimited queue service. Size connection pools, storage, IOPS and WAL for accepted sends, receives, deletes, visibility changes, retries and cleanup together. Long polls wait outside database transactions. The single-message receive mechanism below permits one message in flight per group. If a group takes T seconds from receive to settlement, its useful completion rate is bounded by roughly 1/T, even when other groups are idle. A larger MaxNumberOfMessages can collect heads from multiple groups; it does not create a ten-message pipeline within one group. Adding consumers or database CPU does not remove that serialization. Compare the separate ordered-batch design before selecting a workload that depends on within-group batching. Requested live counts scan the message population even for a single requested counter. Frequent depth polling over a large backlog competes for database I/O and pool capacity; receipt classification can change index/heap work. Price those queries separately from sends and completed message cycles. A fall in depth can reflect purge, expiry or dead-letter transfer rather than application completion. The portable Standard-queue benchmark does not establish the capacity of this host, its HA configuration or a FIFO workload. Payload sizes, active-group skew, settlement time, backlog growth and matched native measurements determine whether a proposed size fits. Missing measurements leave capacity unknown.Retries, batches and application changes
The application keeps its SQS SDK and uses the adapter’s configured endpoint and authentication. Backend IAM, database schema permissions and TLS identity belong to the deployment; an AWS ARN or policy is not automatically a target-cloud authorization grant. Scope identities to the customer resources and keep rotated credentials out of message bodies and receipt handles. A batch response reports each entry separately. Retry only failed entries whose outcome is known; a request timeout can follow a committed send or delete. Keep the same effective deduplication ID on uncertain retries. Duplicate enqueue suppression does not make consumer side effects exactly once. SDK retries and adapter retries share one bounded deadline, with backoff for provider throttling. An expired observer deadline does not prove a still-running native operation was cancelled. Visibility expiration permits another delivery while an earlier worker can still be executing. Consumers use idempotent writes, choose a visibility duration that covers normal processing and handle stale receipt errors. Retention can expire a message in flight. Queues start empty: drain the source before cutover, group by group. Queue recreation and purge must invalidate old claims independently of public names; data cleanup can continue after logical retirement. Database or broker backup is a resource recovery mechanism, not an automatic replay of application side effects.PostgreSQL queue behavior
Your application keeps its SQS SDK and uses the authenticated Cloud Adapter endpoint configured for the install. The adapter performsSendMessage and ReceiveMessage in the SQS-owned PostgreSQL message database and returns SQS responses, error codes and MD5 checksums. Its message-data login is separate from other services and the shared control catalog.
Each queue is a PostgreSQL table with one row per message. Sending, receiving, deleting, delays, visibility, dead-letter delivery and message counts all work on those rows. FIFO queues add ordering by message group, per-group sequence numbers and duplicate detection. Consumers can still receive a message more than once.
The application keeps its SQS SDK. The adapter stores each queue in a PostgreSQL table.
Architecture
The adapter keeps all queue state in PostgreSQL, including messages and receipt handles, so adapter instances can restart or scale out without losing track of in-flight messages. On Cloud SQL and Azure Flexible Server it signs in with short-lived Cloud SQL IAM or Microsoft Entra tokens used as database passwords, so no static secret is stored. When the stack is deployed, Tensor9 creates one database per Cloud Adapter deployment and one table per declared queue. Each row holds the message body and attributes, its message group, its visibility time, its receipt handle, its receive count and the time it was sent. A FIFO queue orders messages within each message group; each row’s arrival position gives its sequence number. A dead-letter queue is another queue table, and a background task deletes messages older than the queue’s retention period. CloudNativePG, Cloud SQL for PostgreSQL, Azure Flexible Server and Scaleway use the same adapter code and tables. They differ in where the data lives: the managed servers run outside your Kubernetes cluster, while CloudNativePG runs inside it. See the rebuild limitation below.Each queue, including each dead-letter queue, is a PostgreSQL table. The same adapter runs on every supported PostgreSQL host.
Receiving messages
One database step selects messages whose visibility timeout has passed, oldest first, up to the requested batch size. In the same step it gives each a new receipt handle, hides it for the visibility timeout, adds one to its receive count and returns it. Messages another receiver is taking at that moment are skipped. FIFO queues return the next eligible message in each group, keeping one in flight per group. When the visibility timeout passes, the message can be delivered again; that does not stop a worker still processing the earlier copy.ApproximateReceiveCount is the actual number of receives, not an estimate. The MD5 checksums of the body and attributes are recomputed, so your SDK’s checks pass. DelaySeconds sets when a message first becomes visible. Long polling waits up to WaitTimeSeconds (at most 20 seconds) and returns as soon as a message is available. SendMessageBatch inserts all entries at once and reports a result for each entry. Message bodies are stored in the queue table.
Two receivers never get the same message at the same time. ApproximateReceiveCount is the actual receive count.
Receipt handles & visibility
Each receive saves a new receipt handle with the message.DeleteMessage and ChangeMessageVisibility find the message by that handle, including after an adapter restart or through another adapter instance.
A delete or visibility change whose handle matches no message returns ReceiptHandleIsInvalid. That includes a message already deleted, or received again under a newer handle. The visibility timeout defaults to 30 seconds. ChangeMessageVisibility can extend it with no lock-duration maximum, and zero makes the message available again immediately. Retention can delete a message while it is in flight.
Receipt handles are saved with messages, so they still work after an adapter restart. Visibility has no lock-duration limit.
Dead-letter & retention
When source and DLQ belong to the same supported SQS-owned message database transaction, receive moves messages atmaxReceiveCount atomically with claiming the rest. Both changes commit or neither does. Cross-database/store transfers are unsupported: sharing a provider, physical server or control log is not a shared message transaction, and no other service’s tables are used. The DLQ retains ordinary queue operations and cleanup. A FIFO move creates a new message in the DLQ, with a new MessageId, a receive count of zero and a new send time.
A background task deletes messages sent longer ago than the queue’s retention period, including messages in flight; receiving does not reset that time. The retention period defaults to four days and is kept between 60 seconds and 14 days, so a missing or too-short value cannot delete new messages straight away. One worker per database removes expired messages in batches, pauses during database maintenance, and continues if one queue fails. Limits on rows per pass and time per batch cap the load.
Atomic DLQ moves require the same supported SQS-owned database transaction. Cross-store moves are unsupported. Retention cleanup removes aged messages.
FIFO ordering & dedup
A FIFO queue stores each message’sMessageGroupId and orders delivery within each group. A receive returns only the oldest message of each group that has nothing in flight (no message in that group is currently received and still hidden). Because arrival positions only increase, that is always the group’s next message, and exactly one message is in flight per group at a time. Groups are independent, so different receivers can process different groups at once, coordinated only by PostgreSQL. When a message’s visibility timeout passes, it is first in its group again, so a redelivery stays in sequence.
Each FIFO send requires MessageGroupId and returns a SequenceNumber: the message’s arrival position as a 20-digit, zero-padded number.
Deduplication markers live in a separate PostgreSQL table keyed by queue and deduplication ID. An explicit MessageDeduplicationId takes precedence; otherwise, on a queue with content-based deduplication, the key is the SHA-256 of the body, excluding attributes. The message insert and deduplication marker are part of one transaction. A duplicate within 5 minutes saves no new message and returns the original MessageId and SequenceNumber. Marker retention is independent of message retention, so receiving or deleting the original does not shorten the deduplication window.
While a message is in flight, no other message from its group is delivered until it is deleted or its visibility timeout passes. That does not stop a timed-out worker from finishing a message it already received, so consumers must make repeated processing safe.
FIFO receives deliver one message per group at a time. Sends return a SequenceNumber, and repeated sends within 5 minutes are suppressed, matched by an explicit ID or, with content-based deduplication, a body hash.
Limitations
Where SQS and the PostgreSQL adapter differ- Throughput behaves differently: one PostgreSQL server serves every queue. All of a Cloud Adapter deployment’s queues share one server, so its capacity bounds peak throughput and a heavy queue can affect the others. In Tensor9’s round-trip test of a moderate-rate Standard queue, the adapter matched SQS throughput (about 300 vs 286 ops/s) with a lower p99 (140 ms vs 172 ms) but a slower median (p50 24 ms vs 15 ms). That is not a measured ceiling, and it does not cover FIFO queues or every host.
- Recovery follows the database placement. The managed database is outside the Cloud Adapter deployment cluster, so replacing that cluster does not replace the queue data. Database availability and recovery still depend on the selected server, HA and backup configuration.
- Messages are limited to 256 KiB by default. The adapter’s default limit is 262144 bytes, while native SQS now accepts up to 1 MiB. Sends are checked against the queue’s declared limit.
- FIFO send deduplication lasts 5 minutes. A duplicate send within that window returns the original IDs. Reusing an ID after the window can create a new message. Consumer redelivery remains possible even within the window.
- Stale receipt handles behave differently: they return an error.
DeleteMessageandChangeMessageVisibilityreturnReceiptHandleIsInvalidwhen no message matches the handle. - Retention behaves differently: expired messages are removed periodically. An expired message can remain until the next cleanup pass. Retention is kept between 60 seconds and 14 days; a too-short value is raised to 60 seconds so that new messages are not deleted.
- Counts observe queue state, not application completion. Requested message counts read the message database: eligible messages are visible, future-visible messages with a receipt are in flight, and future-visible messages without a receipt are initially delayed. These categories share one query snapshot and can change immediately afterward. Metadata-only reads do not require a message-table count. An unavailable requested count returns an explicit unsupported result rather than zero. Purge, expiry and dead-letter movement can reduce depth without completing the application’s work.
- Queue creation behaves differently: queues are created when the stack is deployed. Tensor9 creates the database and each queue’s table, and its dead-letter table, at deploy time.
CreateQueue,DeleteQueueandSetQueueAttributesact on those tables. Switching a queue between Standard and FIFO is rejected, because it would replace the queue.
Other considerations
- Moving from AWS. The database and queue tables start empty, and existing SQS messages are not migrated. Drain each group before switching it, to preserve order.
- Removing queues. Each queue is created in one step, so a crash never leaves a half-created queue. When a queue is removed from the stack, Tensor9 deletes only queues it created; any other queue is detached and left in place. A queue that still holds messages is not deleted unless deletion is forced.
- Who operates what. On the managed hosts, the provider operates the database’s durability, backups and high availability, and Tensor9 operates the adapter. On CloudNativePG, Tensor9 operates the database inside your cluster.
Example monthly charges
This Tensor9 Cloud Adapter scenario estimates service charges for the named origin and target services. Adapter hosting and commercial Tensor9 fees need separate allocations. How Tensor9 estimates costs explains the method and what the estimates include.SQS FIFO · SQS request billing units
Feature: SQS FIFO. Estimated monthly service charges by SQS request billing units. Adapter hosting and Tensor9 fees are excluded. Source: us-east-1; target: fr-par; currency: USD.- 1-KiB messages, unbatched send/receive/delete; actual batch and delivery assumptions stay visible. Other native meters and workload assumptions retain their explicitly displayed default quantities. Workload translation and capacity assumptions are not benchmark measurements.
- Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts. Rates as of 2026-10-22: us-east-1 → fr-par, USD/month.
- Source prices are reference charges, not an invoice. Target lines cover selected service usage/configuration only; adapter hosting and Tensor9 fees are excluded.
- Samples of explicit prices are not performance measurements or capacity qualification. No interpolation or break-even guarantee is implied.
- Variant assumptions show the first axis sample; any axis-dependent configuration is described by this curve’s workload note.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Scaleway Managed Database for PostgreSQL at Production Optimized (PRO2) prices in EUR converted at the ECB reference rate. A high-availability or replica node bills Scaleway’s ‘Additional nodes’ price, EUR 0.0583 per hour for PRO2-XXS, 53% of the main node. Scaleway lists no egress charge for Managed Databases, so selected network is not charged. Cost Optimized ranges (DB-DEV-S from EUR 0.0156 per hour), Block Storage 15K and backups (EUR 0.03 per GB-month) are not selected.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: DB-PRO2-L has 32 vCPUs and 128 GB (https://www.scaleway.com/en/pricing/managed-databases/); a volume grows up to 15 TB (https://www.scaleway.com/en/docs/managed-databases-for-postgresql-and-mysql/concepts/).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
- AWS Price List API, AWSQueueService offer: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSQueueService/current/us-east-1/index.json
- Scaleway Managed Databases pricing: https://www.scaleway.com/en/pricing/managed-databases/
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
plan-587f83be80f7d547d383d9abce0fac6d8798d699 / 2026-10-22.planning.2. Curve: workload-1.
Sources: AWS Price List API, AWSQueueService offer, Scaleway Managed Databases pricing.
SQS FIFO → Scaleway Managed Database for PostgreSQL: Authored native-usage planning example. Native monthly usage priced at the cited provider list prices; listed target allowances apply where present, excluding invoice credits, taxes and negotiated discounts.
Scenario source region: us-east-1. Scenario target region: fr-par. Currency: USD.
- Additional network transfer, backups, KMS, one-time migration and operational labor unless an explicit meter includes them.
- Destination application execution and separately billed downstream services; supply those allocations separately.
- Taxes, discounts, credits and free-tier allowances not explicitly listed by this model.
- Unmodeled dependent services, task execution and operations outside the selected workload family.
- Translated reads: 0 operations.
- Translated writes: 0 operations.
- Translated resident physical data: 0 GiB-month.
- Native provider operations: 0 operations.
- Published payload: 0 GiB.
- Delivered payload: 0 GiB.
- Allocated execution CPU: 0 vCPU-hour.
- Allocated execution RAM: 0 GiB-hour.
- Independent resource allocation: 0 resource-hour.
- Independent inventory: 0 resource-month.
- Input tokens: 0 tokens.
- Output tokens: 0 tokens.
- Billable network: 0 GiB.
- Dependent object sink retained data: 0 GiB-month.
- Dependent object sink writes: 0 writes.
- Rates are cited provider list prices, editable for discounts, commitments or another region. Workload translation and capacity coefficients remain editable planning assumptions, not benchmark measurements or a commercial quote.
- Default-zero rates are explicit assumptions, not evidence that the deployed service or resource is free.
- Provisioned-unit minimums use an editable approximate allocation floor. Modeled target service cost is max(usage/allocation, minimum), with billable network, durable staging and dependent sinks added separately; actual RU/TU sizing, scaling increments and throughput remain unqualified.
- Durable staging is priced once: provisioned targets include adapter state in their selected allocation; native targets add a separate staging allocation when required. Adapter hosting is a separate allocation and must exclude resources already priced as staging, workers or target capacity.
- A declared adapter mapping and cost model do not establish implementation availability or service equivalence.
- This is a declared directed mapping; a planning estimate does not establish deployment or request-serving support.
- Authored planning assumptions, not measured adapter capacity. Origin rates are cited first-tier list prices, before free allowances and discounts.
- A cost scenario does not establish backend availability, protocol fidelity or production readiness. Registry serving status remains independent.
- Storage follows resident original messages, not every monthly message. Broker delivery bytes include redeliveries.
- FIFO estimates do not qualify dedup support, group throughput or single-group latency; backend limitations remain applicable.
- Scaleway Managed Database for PostgreSQL at Production Optimized (PRO2) prices in EUR converted at the ECB reference rate. A high-availability or replica node bills Scaleway’s ‘Additional nodes’ price, EUR 0.0583 per hour for PRO2-XXS, 53% of the main node. Scaleway lists no egress charge for Managed Databases, so selected network is not charged. Cost Optimized ranges (DB-DEV-S from EUR 0.0156 per hour), Block Storage 15K and backups (EUR 0.03 per GB-month) are not selected.
- Row-store throughput (capacityOpsPerVcpuSecond, default 1500) is measured-by-tensor9 as a lower bound: the DynamoDB adapter on Cloud SQL db-custom-2-7680 (2 vCPU, PostgreSQL 16, us-west1) served 2,974 ops/s of YCSB-A at 16 threads without recorded saturation (src/main/kotlin/t9/prime/equiv/generated/eval/CloudsqlPostgresqlYcsbAT16GoYcsbV1_0_0.kt). Published CPU-bound pgbench reaches 3,101 read-write transactions and 20,289 point reads per vCPU-second (AWS z1d.2xlarge, PostgreSQL 14.5), so actual capacity is likely higher. Reads and writes share one coefficient: at the same adapter version, read-only YCSB-C was not faster than 50%-update YCSB-A.
- Log-broker throughput (capacityStreamMiBPerVcpuSecond 20 at 0.5 utilization, 4 GiB RAM per vCPU) is provider-documented by Google Managed Service for Apache Kafka sizing (https://docs.cloud.google.com/managed-service-for-apache-kafka/docs/plan-cluster-size): write-equivalent bytes are replicated writes plus a quarter of reads. Producer batches below 10 KB lower per-CPU throughput; that penalty is not modeled.
- Disk utilization 0.8 is provider-documented headroom below Cloud SQL automatic storage increase, which triggers near 91-95% full (https://docs.cloud.google.com/sql/docs/postgres/instance-settings). The 20 GiB reserve exceeds PostgreSQL’s 1 GB default max_wal_size; the remainder of that reserve is unmeasured.
- CPU tiers double from 2 vCPUs to the target’s largest node at 4 GiB per vCPU; each target’s documented largest node bounds CPU, RAM, RAM per vCPU and disk, and the durable staging database uses Cloud SQL Enterprise (96 vCPU, 6.5 GiB per vCPU, 624 GiB, 64 TiB). Targets billed per capacity unit or throughput unit are sized by their backend instead.
- No public evidence: peak/mean work (2) and the RAM working-set fraction (0.1). Proposed measurements: the p99 one-minute rate over the monthly mean from customer CloudWatch metrics; the buffer hit ratio while stepping RAM under a fixed YCSB-B load.
- Node bounds: DB-PRO2-L has 32 vCPUs and 128 GB (https://www.scaleway.com/en/pricing/managed-databases/); a volume grows up to 15 TB (https://www.scaleway.com/en/docs/managed-databases-for-postgresql-and-mysql/concepts/).
- Stored GiB already includes the origin family’s physical footprint assumptions; no second storage amplification is applied.
- The operations/vCPU coefficient supplies the compute requirement alongside explicit resource-hour minima.
- Copies and allocation fractions change cost only; they do not increase modeled primary capacity.
plan-587f83be80f7d547d383d9abce0fac6d8798d699 / 2026-10-22.planning.2. Scenario: planning-example.
Sources: AWS Price List API, AWSQueueService offer, Scaleway Managed Databases pricing.
Costs
Estimated monthly service charges for each backend with a published cost model, at one sampled workload from that model’s cost curve. Adapter hosting and Tensor9 fees are excluded. How Tensor9 estimates costs explains the method, what the estimates include and how to read their qualifications.Service level agreements
Listed terms cover requests sent through this service adapter. They do not cover direct connections to the target service or replace the cloud provider’s own SLA. Each origin-to-target pair has its own terms or an explicit pending status. See the SLA tables, measurement rules, and scaling conditions.SQS to Cosmos DB
Why these latency targets differ
The shared Standard/FIFO point-operation target is 20 ms, with 200 ms for a batch of up to ten sends. Cosmos FIFO uses a per-group sequence counter, a durable deduplication marker and an in-flight ownership slot. Their conditional reads/writes are adapter coordination; the clock cannot exclude them merely because they use Cosmos DB. The shared target preserves room for that work instead of advertising the cost of a simple native queue forwarder. Ready-message pickup and delay after the requested wait remain at 500 ms. Discovery, candidate inspection, conditional claims and polling can dominate this path even for a tiny message. The target is not an end-to-end promise for clearing a backlog, and Standard and FIFO observations must remain separate.Adapter and scope
Receive timing
Two phases ofReceiveMessage have separate measurements:
- Ready-message pickup: time from a message becoming available to a waiting receiver until the adapter sends the response. Only separately measured time spent waiting for the backend service is excluded.
- Delay after the requested wait: extra adapter time after the requested wait for a message has ended.
Message guarantees
A send can return success only after the message state has been durably saved. A deduplication marker alone must not produce success for a message that was never committed. The adapter must use the same record of accepted messages when returning success, checking for duplicates, and recovering from a crash. Standard queues can redeliver messages. FIFO preserves the profile’s per-group ordering and supported deduplication behavior; it does not promise global order across groups or exactly-once effects in your application. A consumer can perform a business action and fail before deleting the message, so application-side idempotency still matters. The adapter follows its documented rules for visibility, expiration, message deletion, and movement to a dead-letter queue. Successfully completed changes must survive the process failures covered by the agreement. An expired receipt handle produces the result documented for that adapter; different backends need not return the same error. Approximate queue counts help with troubleshooting but are not guaranteed to show the exact current queue depth.Useful throughput
Count completed API calls separately from message work. A valid emptyReceiveMessage completes an API call but delivers no message. One successful send, nonempty receive and delete form a message lifecycle involving at least three API calls. Redelivery and internal retries must not inflate the count of distinct messages processed.
Measure Standard and FIFO separately. FIFO group distribution, time between receive and delete, visibility timeout, delayed messages and dead-letter traffic change the scaling limit. A large number of consumers cannot make a single serialized group behave like many independent groups.
These standard service levels do not reserve a fixed message rate or specify a maximum throughput. Tensor9 and the customer must agree on limits for the actual workload and production deployment, including how quickly traffic can grow and how large a burst can be. Autoscaling is intended to maintain the stated latency and endpoint reachability within those limits. It cannot remove ordering requirements or backend-service limits.
Operation terms
The named operations retain their documented behavior with supported request options. The 1 KiB limits apply to the latency targets.DeleteMessageBatch, ChangeMessageVisibilityBatch, queue management, tagging and approximate-count reads have no numerical SLA under these standard terms. A capability in the service profile does not automatically receive another operation’s SLA.
The pickup service level differs from the Cloud SQL service level. These targets apply to their respective receive paths; they are not comparative benchmark results or a recommendation to choose one backend.
Scaling on Cosmos DB
Partition distribution, conditional message claims, deduplication and FIFO group serialization affect useful throughput. Native request-unit consumption and throttling need to be considered alongside adapter scheduling, repeated scans and retry amplification. Additional replicas can process independent work. They do not remove contention around the same message claim or FIFO group, and they do not grant additional native serverless capacity. Track completed message lifecycles, native calls per lifecycle and repeated failed claims separately. Once a message expires, the queue must treat it as expired even if the cloud provider has not yet removed its stored data. Do not count expired messages as available work merely because they still appear in a storage view. Time the adapter takes to find an available message, including waits between queue checks, also counts toward adapter latency. It is not automatically excluded as cloud-provider time.Example: two receivers see the same candidate
Two receivers discover a message. The adapter must use a conditional update to assign the message to a receiver under the documented queue rules. It must not give both receivers conflicting ownership just to meet a latency target. Record the claim outcomes and native conditional responses, along with local retries and scheduling. A later redelivery after visibility expires can be legitimate. It is different from simultaneous ownership caused by a broken claim. Inspect receipt timing and the selected queue semantics before calling either event data loss or a duplicate-delivery defect.Example: restart during a dead-letter transition
A message is copied to the dead-letter queue, then the process restarts before removing the source copy. Recovery must preserve the supported message semantics without adapter-induced loss. A valid redelivery is not the same as a missing accepted message. Preserve source and destination observations and identifiers before changing either queue. Do not delete both copies to make the counts agree, and do not replay a send solely to generate an Explain report. If Cosmos DB also reports throttling, investigate serverless/partition pressure and the adapter’s call/retry pattern. Backend throttling does not excuse an incorrect recovery algorithm or excessive local retries.Evidence for support
Record Standard versus FIFO, group distribution, message and attribute sizes, conditional-claim outcomes, wait/visibility settings, dead-letter configuration and the affected time window. Include native request IDs, request-unit/throttling observations and available adapter timing. Keep sensitive bodies and receipt handles out of shared reports. You can contact support before you know what caused the problem.SQS (Simple Queue Service, FIFO queues) to PostgreSQL Flexible Server
What this adapter does
Forazure::1.0.0::postgresql::flexible, The SQL queue uses row locking and SKIP LOCKED; FIFO adds head-of-group selection and deduplication state. The current long-poll loop can sleep between polls. Queue configuration is cached and durable queue state remains in PostgreSQL. A ReceiveMessage response budget is not a delivery-time promise: messages may not yet exist, may be delayed, or may be blocked by a FIFO group head. The short-poll row deliberately removes that ambiguity. Requested long-poll waits need their own measurement treatment in the agreement.
How the latency targets were chosen
Small message send and settlement: +10 ms monthly p99 (adapter-added).ChangeMessageVisibility, DeleteMessage, SendMessage. Native forwarding needs bounded translation; SQL adds queue state; Cosmos FIFO requires multiple durable coordination steps and cannot honestly inherit a 1 ms forwarding budget.
Bounded short-poll receive: +10 ms monthly p99 (adapter-added). ReceiveMessage. Receive scans/selects candidates, claims visibility and creates receipt handles. FIFO head selection and Cosmos slot CAS cost more than a simple send.
Bounded message batches: +100 ms monthly p99 (adapter-added). DeleteMessageBatch, SendMessageBatch. A conservative upper budget for up to ten point paths plus aggregation. It does not assume the implementation parallelizes all target or metadata work.
Queue configuration and discovery: +20 ms monthly p99 (adapter-added). GetQueueAttributes, GetQueueUrl. Queue identity, attributes, tags and counts can use the adapter’s durable catalog; this is not excluded as target message work.
Your signed agreement sets the terms for your deployment. A target does not add an operation or option that the compatibility tables mark unavailable.
What counts toward latency
For a request-response row, measure from the agreed ingress boundary to dispatch of the complete response. A row that explicitly names a first response chunk ends at that chunk; its number does not cover the rest of the stream. A long-poll row names the intentional wait and when adapter delay starts. Include parsing, authorization, admission, translation, serialization, adapter-owned storage and coordination, retries and response handling. Subtract only separately measured target-workload waits and external network segments allowed by the measurement rules. The adapter’s own response handling and dispatch remain covered. A database used for adapter metadata is still adapter work, even if a cloud provider hosts it. For concurrent calls, exclude the union of permitted wait intervals, not the sum of overlapping spans. Calculate each request’s adapter duration first, then the monthly p99. Do not subtract one service’s p99 from another’s. Known adapter timeouts are over-budget samples; failed or incomplete requests cannot disappear to improve the percentile. Missing measurements do not become zero latency. An SDK call span alone does not prove how much of its duration can be excluded.Endpoint reachability and request failures
The endpoint-reachability target measures adapter health checks. Correctly forwarding a target quota or permission error is different from producing that error because the adapter sent the wrong request. Adapter-caused failures remain Tensor9’s responsibility even when the target is healthy. Correctness and data-integrity requirements apply to every supported request. Endpoint reachability does not measure request correctness or grant an allowance for incorrect results.Scaling and target-service capacity
Scale send, receive and settle capacity together, and track in-flight messages, pollers, candidate scans and FIFO group skew. Adding replicas helps independent groups but cannot parallelize the ordered head of one group. The agreement caps active pollers, groups inspected per receive, message bytes, retry amplification and batch entries. Tensor9 scales the fabric within those limits; the customer supplies sufficient broker capacity, Cosmos RU/s or PostgreSQL connections and I/O. Tell Tensor9 the expected steady rate, bursts, concurrency, payload sizes and operation mix. Tensor9 sizes and scales the adapter for the agreed load; you choose and monitor the target service’s capacity with Tensor9’s help. A latency budget is not a requests-per-second rating. Larger requests and higher rates need explicit terms, not silent inheritance of a small-request SLA.Data and behavior guarantees
Acceptance must not be returned before the documented message persistence point. Settlement must apply to the intended message/receipt; FIFO order and deduplication apply only where this directed profile supports them. Duplicate delivery can be legitimate under at-least-once delivery. Dead-letter transitions must not silently discard an accepted message. Durability of the target broker/database remains its own commitment, while broken adapter receipt, marker or coordination logic remains Tensor9’s responsibility.Example and diagnosis
Fororder-events, send a 2 KiB message, receive up to ten messages with WaitTimeSeconds=0, then settle each receipt. For a FIFO queue, distribute independent customers across groups instead of expecting one group to scale with replicas. If native message writes are fast but Cosmos FIFO sends slow down, inspect counter/dedup contention: those coordination waits still count against Tensor9’s fabric budget.
Use tensor9 explain and the documented explain headers to understand the selected adapter and its behavior. Correlate available request diagnostics with the target provider’s latency, throttling and capacity metrics. An explain report helps diagnose a request; it is not by itself a qualified SLA timing measurement. Share the operation, request shape, timestamps and request identifiers with support, with credentials and customer payloads removed.
SQS (Simple Queue Service, FIFO queues) to Azure Service Bus
What this adapter does
Forazure::1.0.0::servicebus, Service Bus messages and locks implement queue delivery; FIFO uses sessions. Lock renewal, receipt mapping and settlement remain adapter responsibilities, while native broker delivery uses the target service. A ReceiveMessage response budget is not a delivery-time promise: messages may not yet exist, may be delayed, or may be blocked by a FIFO group head. The short-poll row deliberately removes that ambiguity. Requested long-poll waits need their own measurement treatment in the agreement.
How the latency targets were chosen
Small message send and settlement: +1 ms monthly p99 (adapter-added).ChangeMessageVisibility, DeleteMessage, SendMessage. Native forwarding needs bounded translation; SQL adds queue state; Cosmos FIFO requires multiple durable coordination steps and cannot honestly inherit a 1 ms forwarding budget.
Bounded short-poll receive: +3 ms monthly p99 (adapter-added). ReceiveMessage. Receive scans/selects candidates, claims visibility and creates receipt handles. FIFO head selection and Cosmos slot CAS cost more than a simple send.
Bounded message batches: +10 ms monthly p99 (adapter-added). SendMessageBatch. A conservative upper budget for up to ten point paths plus aggregation. It does not assume the implementation parallelizes all target or metadata work.
Queue configuration and discovery: +20 ms monthly p99 (adapter-added). DeleteQueue, ListQueueTags, ListQueues, PurgeQueue, SetQueueAttributes, TagQueue, UntagQueue. Queue identity, attributes, tags and counts can use the adapter’s durable catalog; this is not excluded as target message work.
Your signed agreement sets the terms for your deployment. A target does not add an operation or option that the compatibility tables mark unavailable.
What counts toward latency
For a request-response row, measure from the agreed ingress boundary to dispatch of the complete response. A row that explicitly names a first response chunk ends at that chunk; its number does not cover the rest of the stream. A long-poll row names the intentional wait and when adapter delay starts. Include parsing, authorization, admission, translation, serialization, adapter-owned storage and coordination, retries and response handling. Subtract only separately measured target-workload waits and external network segments allowed by the measurement rules. The adapter’s own response handling and dispatch remain covered. A database used for adapter metadata is still adapter work, even if a cloud provider hosts it. For concurrent calls, exclude the union of permitted wait intervals, not the sum of overlapping spans. Calculate each request’s adapter duration first, then the monthly p99. Do not subtract one service’s p99 from another’s. Known adapter timeouts are over-budget samples; failed or incomplete requests cannot disappear to improve the percentile. Missing measurements do not become zero latency. An SDK call span alone does not prove how much of its duration can be excluded.Endpoint reachability and request failures
The endpoint-reachability target measures adapter health checks. Correctly forwarding a target quota or permission error is different from producing that error because the adapter sent the wrong request. Adapter-caused failures remain Tensor9’s responsibility even when the target is healthy. Correctness and data-integrity requirements apply to every supported request. Endpoint reachability does not measure request correctness or grant an allowance for incorrect results.Scaling and target-service capacity
Scale send, receive and settle capacity together, and track in-flight messages, pollers, candidate scans and FIFO group skew. Adding replicas helps independent groups but cannot parallelize the ordered head of one group. The agreement caps active pollers, groups inspected per receive, message bytes, retry amplification and batch entries. Tensor9 scales the fabric within those limits; the customer supplies sufficient broker capacity, Cosmos RU/s or PostgreSQL connections and I/O. Tell Tensor9 the expected steady rate, bursts, concurrency, payload sizes and operation mix. Tensor9 sizes and scales the adapter for the agreed load; you choose and monitor the target service’s capacity with Tensor9’s help. A latency budget is not a requests-per-second rating. Larger requests and higher rates need explicit terms, not silent inheritance of a small-request SLA.Data and behavior guarantees
Acceptance must not be returned before the documented message persistence point. Settlement must apply to the intended message/receipt; FIFO order and deduplication apply only where this directed profile supports them. Duplicate delivery can be legitimate under at-least-once delivery. Dead-letter transitions must not silently discard an accepted message. Durability of the target broker/database remains its own commitment, while broken adapter receipt, marker or coordination logic remains Tensor9’s responsibility.Example and diagnosis
Fororder-events, send a 2 KiB message, receive up to ten messages with WaitTimeSeconds=0, then settle each receipt. For a FIFO queue, distribute independent customers across groups instead of expecting one group to scale with replicas. If native message writes are fast but Cosmos FIFO sends slow down, inspect counter/dedup contention: those coordination waits still count against Tensor9’s fabric budget.
Use tensor9 explain and the documented explain headers to understand the selected adapter and its behavior. Correlate available request diagnostics with the target provider’s latency, throttling and capacity metrics. An explain report helps diagnose a request; it is not by itself a qualified SLA timing measurement. Share the operation, request shape, timestamps and request identifiers with support, with credentials and customer payloads removed.
SQS (Simple Queue Service, FIFO queues) to Cloud SQL for PostgreSQL
SLA status: Not applicable FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability.SQS (Simple Queue Service, FIFO queues) to PostgreSQL
SLA status: Not applicable FIFO request-processing service levels have not been qualified for this mapping. Standard-queue measurements do not establish FIFO latency, throughput or availability.SQS (Simple Queue Service, FIFO queues) to Scaleway Managed Database for PostgreSQL
What this adapter does
Forscaleway::1.0.0::rdb::postgresql, The SQL queue uses row locking and SKIP LOCKED; FIFO adds head-of-group selection and deduplication state. The current long-poll loop can sleep between polls. Queue configuration is cached and durable queue state remains in PostgreSQL. A ReceiveMessage response budget is not a delivery-time promise: messages may not yet exist, may be delayed, or may be blocked by a FIFO group head. The short-poll row deliberately removes that ambiguity. Requested long-poll waits need their own measurement treatment in the agreement.
How the latency targets were chosen
Small message send and settlement: +10 ms monthly p99 (adapter-added).ChangeMessageVisibility, DeleteMessage, SendMessage. Native forwarding needs bounded translation; SQL adds queue state; Cosmos FIFO requires multiple durable coordination steps and cannot honestly inherit a 1 ms forwarding budget.
Bounded short-poll receive: +10 ms monthly p99 (adapter-added). ReceiveMessage. Receive scans/selects candidates, claims visibility and creates receipt handles. FIFO head selection and Cosmos slot CAS cost more than a simple send.
Bounded message batches: +100 ms monthly p99 (adapter-added). DeleteMessageBatch, SendMessageBatch. A conservative upper budget for up to ten point paths plus aggregation. It does not assume the implementation parallelizes all target or metadata work.
Queue configuration and discovery: +20 ms monthly p99 (adapter-added). GetQueueAttributes, GetQueueUrl. Queue identity, attributes, tags and counts can use the adapter’s durable catalog; this is not excluded as target message work.
Your signed agreement sets the terms for your deployment. A target does not add an operation or option that the compatibility tables mark unavailable.
What counts toward latency
For a request-response row, measure from the agreed ingress boundary to dispatch of the complete response. A row that explicitly names a first response chunk ends at that chunk; its number does not cover the rest of the stream. A long-poll row names the intentional wait and when adapter delay starts. Include parsing, authorization, admission, translation, serialization, adapter-owned storage and coordination, retries and response handling. Subtract only separately measured target-workload waits and external network segments allowed by the measurement rules. The adapter’s own response handling and dispatch remain covered. A database used for adapter metadata is still adapter work, even if a cloud provider hosts it. For concurrent calls, exclude the union of permitted wait intervals, not the sum of overlapping spans. Calculate each request’s adapter duration first, then the monthly p99. Do not subtract one service’s p99 from another’s. Known adapter timeouts are over-budget samples; failed or incomplete requests cannot disappear to improve the percentile. Missing measurements do not become zero latency. An SDK call span alone does not prove how much of its duration can be excluded.Endpoint reachability and request failures
The endpoint-reachability target measures adapter health checks. Correctly forwarding a target quota or permission error is different from producing that error because the adapter sent the wrong request. Adapter-caused failures remain Tensor9’s responsibility even when the target is healthy. Correctness and data-integrity requirements apply to every supported request. Endpoint reachability does not measure request correctness or grant an allowance for incorrect results.Scaling and target-service capacity
Scale send, receive and settle capacity together, and track in-flight messages, pollers, candidate scans and FIFO group skew. Adding replicas helps independent groups but cannot parallelize the ordered head of one group. The agreement caps active pollers, groups inspected per receive, message bytes, retry amplification and batch entries. Tensor9 scales the fabric within those limits; the customer supplies sufficient broker capacity, Cosmos RU/s or PostgreSQL connections and I/O. Tell Tensor9 the expected steady rate, bursts, concurrency, payload sizes and operation mix. Tensor9 sizes and scales the adapter for the agreed load; you choose and monitor the target service’s capacity with Tensor9’s help. A latency budget is not a requests-per-second rating. Larger requests and higher rates need explicit terms, not silent inheritance of a small-request SLA.Data and behavior guarantees
Acceptance must not be returned before the documented message persistence point. Settlement must apply to the intended message/receipt; FIFO order and deduplication apply only where this directed profile supports them. Duplicate delivery can be legitimate under at-least-once delivery. Dead-letter transitions must not silently discard an accepted message. Durability of the target broker/database remains its own commitment, while broken adapter receipt, marker or coordination logic remains Tensor9’s responsibility.Example and diagnosis
Fororder-events, send a 2 KiB message, receive up to ten messages with WaitTimeSeconds=0, then settle each receipt. For a FIFO queue, distribute independent customers across groups instead of expecting one group to scale with replicas. If native message writes are fast but Cosmos FIFO sends slow down, inspect counter/dedup contention: those coordination waits still count against Tensor9’s fabric budget.
Use tensor9 explain and the documented explain headers to understand the selected adapter and its behavior. Correlate available request diagnostics with the target provider’s latency, throttling and capacity metrics. An explain report helps diagnose a request; it is not by itself a qualified SLA timing measurement. Share the operation, request shape, timestamps and request identifiers with support, with credentials and customer payloads removed.
Install and run
The documentation and SLAs are public. Downloading and running the Cloud Adapter binary requires an entitled customer account. SetT9_API_KEY as described in Install and Authenticate, then list the adapters your account may use with this origin: