Durable ObjectsCookbook
Quickstart
Track an order through a fulfilment pipeline with a Durable Object.
Prerequisites
- A Pingerchips app with an App Key and App Secret
- Node.js 18+
1. Install
npm install pingerchips-js-serverESM only — add "type": "module" to package.json or use .mjs.
2. Write from your server
// server.js
import PingerchipsServer from 'pingerchips-js-server';
const pc = new PingerchipsServer(
process.env.PINGERCHIPS_APP_KEY,
process.env.PINGERCHIPS_APP_SECRET
);
const order = pc.object('order', 'order-42');
// individual slots
await order.set('status', 'pending');
await order.set('assigned_to', 'agent-7');
// multiple slots, atomic (one batch event)
await order.setAll({
status: 'processing',
started_at: Date.now(),
});
// append to a list slot
await order.append('history', {
event: 'processing_started',
by: 'agent-7',
at: Date.now(),
});
// atomic increment
const { value } = await order.increment('retry_count');
console.log('retry count:', value); // 13. Read it back
const state = await order.state();
// { status: "processing", assigned_to: "agent-7", retry_count: 1, history: [...], log_id: 5 }
const status = await order.get('status'); // "processing"4. Atomic multi-write
Use a transaction when several slots must change together:
await order.transaction([
{ op: 'set', key: 'status', value: 'shipped' },
{ op: 'append', key: 'history', value: { event: 'shipped', at: Date.now() } },
]);All operations commit in one log entry, or none do.
The transaction is write-only — it can't read the current value. To ship an
order only if it is still processing, read first and decide in your code:
if ((await order.get('status')) === 'processing') {
await order.transaction([
{ op: 'set', key: 'status', value: 'shipped' },
]);
}5. Read over HTTP (any language)
curl "https://queue.pingerchips.com/api/v1/objects/$APP_KEY/order/order-42" \
-H "X-App-Key: $APP_KEY" \
-H "X-App-Secret: $APP_SECRET"Two headers, no signing — see Authentication.
{
"state": { "status": "shipped", "assigned_to": "agent-7", "retry_count": 1 },
"log_id": 7
}6. Watch changes live in the browser
Add an auth endpoint (App Secret stays server-side):
import PingerchipsServer from 'pingerchips-js-server';
const pc = new PingerchipsServer(
process.env.PINGERCHIPS_APP_KEY,
process.env.PINGERCHIPS_APP_SECRET,
);
app.post('/auth/durable', (req, res) => {
const { socket_id, object_type, object_key } = req.body;
// your authorization check here
res.json(pc.authenticateObject(socket_id, object_type, object_key));
});Then subscribe from the browser:
import Pingerchips from 'pingerchips-js';
const pc = new Pingerchips('YOUR_APP_KEY', { authEndpoint: '/auth/durable' });
const order = await pc.object('order', 'order-42');
console.log(order.state); // populated from the snapshot
order.on('change:status', ({ value }) => updateBadge(value));See the Client SDK for the full event set and resumable reconnect.
What's next
- Concepts — slots, the log, rehydration
- Server SDK — full Node.js API
- HTTP API — every REST endpoint
- Architecture — RocksDB, ring routing, quorum