Skip to content
GigadriveDocs

Sending messages

Send a message now, after a delay or at a set time, deduplicate repeats, keep related messages in order, and send in batches.

A send stores the message durably before it returns, so once you have a message id the message survives a crash on either side. Every option on this page works the same for push and pull queues.

Send a message

The payload can be any JSON value. A Uint8Array or ArrayBuffer travels as raw bytes instead.

import { queue } from '@gigadrive/sdk';

const invoices = queue<{ invoiceId: string }>('invoices');

const sent = await invoices.send({ invoiceId: 'inv_2041' });

console.log(sent.messageId, sent.deliverAt);

Inside a deployed Function, queue() needs no configuration: it authenticates with the Function's own credential, described in OIDC federation. A REST call needs a token with the network:queues:send scope, which a deployed Function's credential already has. Sending to a name that does not exist creates a pull queue with default settings; pass autoCreate: false to the queue handle, or "autoCreate": false in REST, to get 404 queue_not_found instead.

Delay or schedule a message

delay holds a message back for a duration, and at delivers it at a point in time. Both reach up to one year ahead, and at wins when you pass both.

await invoices.send({ invoiceId: 'inv_2041' }, { delay: '15m' });
await invoices.send({ invoiceId: 'inv_2041' }, { at: new Date('2027-01-01T09:00:00Z') });

A duration is a number of seconds or a string such as '30s', '15m', '12h' or '7d'. In REST, send delaySeconds or an ISO 8601 deliverAt.

A delayed message's retention period starts when it becomes due, so a message scheduled a month out is still kept for the full period after that. Scheduled messages appear under Scheduled on the queue's Messages tab in the console.

Cancel a scheduled message

Keep the message id from the send, then delete the message before it is processed:

const { messageId } = await invoices.send({ invoiceId: 'inv_2041' }, { delay: '7d' });

await invoices.cancel(messageId);

The REST equivalent is DELETE /applications/{applicationId}/queues/{queue}/messages/{messageId}. A message that was already processed answers 404 message_not_found, and one that is being delivered or was dead-lettered answers 400 invalid_request: settle it from its consumer, or purge or retry dead letters from the queue's page.

Deduplicate repeated sends

Give a message a deduplication key, and any later send with the same key inside the queue's deduplication window is dropped. The duplicate send still succeeds: it returns the first message's id with deduplicated: true.

const first = await invoices.send({ invoiceId: 'inv_2041' }, { deduplicationKey: 'invoice:inv_2041' });
const again = await invoices.send({ invoiceId: 'inv_2041' }, { deduplicationKey: 'invoice:inv_2041' });

console.log(again.messageId === first.messageId, again.deduplicated); // true true

The window is 24 hours by default and up to seven days, set per queue. Keys are up to 256 characters.

Messages that share a groupKey are delivered one at a time, in the order you sent them. The next message in a group waits until the one before it is acknowledged, dead-lettered or expired, while other groups and ungrouped messages keep flowing.

const orders = queue<{ orderId: string; event: string }>('order-events');

await orders.send({ orderId: 'ord_77', event: 'paid' }, { groupKey: 'ord_77' });
await orders.send({ orderId: 'ord_77', event: 'shipped' }, { groupKey: 'ord_77' });

Use one group per entity, such as an order or a customer. One group shared by every message makes the whole queue sequential.

Pin a message to a deployment

A push message goes to the environment's current deployment by default. Pass deploymentId to deliver it to a specific deployment instead, for example the one that sent it, so a payload format change in a new deployment cannot meet an old message:

await invoices.send({ invoiceId: 'inv_2041' }, { deploymentId: process.env.GIGADRIVE_DEPLOYMENT_ID });

The deployment must belong to the queue's environment; another one is refused with 400 invalid_request. When the pinned deployment no longer serves the environment, the message goes to the current deployment, and the delivery carries x-gigadrive-queue-deployment-fallback: 1.

Send a batch

sendBatch sends up to 100 messages per request and splits larger arrays into requests of 100. Each message carries its own options, and the results come back in the same order:

const results = await invoices.sendBatch([
  { payload: { invoiceId: 'inv_2041' } },
  { payload: { invoiceId: 'inv_2042' }, delay: '1h' },
]);

for (const result of results) {
  if (result.error) console.error(result.error.code);
}

One refused message does not fail the others. sendBatch splits by count only, and a request whose message bodies add up to more than 4 MiB is refused whole with 400 invalid_request, so send large payloads in smaller batches. In REST, send messages: [...] instead of the single-message fields.

Headers

Add headers to forward metadata with each push delivery, such as a tenant id or a trace header. A message can carry up to 32 headers, each value up to 1,024 characters. These names are reserved and refused with 400 invalid_request:

  • Transport headers: host, content-length, content-type, connection, transfer-encoding, te, upgrade, keep-alive, authorization, cookie, and any name starting with proxy-.
  • Platform and proxy headers: any name starting with x-gigadrive-, x-nebula-, x-substrate-, x-vercel-, x-forwarded- or x-bunny-, and x-real-ip, true-client-ip and forwarded.

Set the content type with contentType instead of a header. Schedules reserve two more names.

When a send is refused

StatuscodeCause
400invalid_requestA malformed option, a payload over 1 MiB, a batch over 4 MiB of bodies, or a reserved header
402billing_cap_reachedThe organization reached its spend cap
404queue_not_foundThe queue does not exist and auto-creation is off
429quota_exceededCreating the queue would exceed the plan's queues per environment
413payload_too_largeThe request is larger than 6 MiB
429backlog_fullThe organization's queued messages reached the plan's storage allowance

The SDK throws an ApiError carrying that code. Limits and pricing lists the allowances per plan.