# Billing LiveObjects operations are billed as messages. This page explains how different LiveObjects operations contribute to your Ably usage. ## Message counting Each operation is sent as an [`ObjectMessage`](https://ably.com/docs/liveobjects/concepts/operations#properties). Ably bills for each outbound message sent from a client, and for each inbound message delivered to each client. When a client performs an operation (such as setting a value on a `LiveMap` or incrementing a `LiveCounter`), this generates an outbound message. When that operation is broadcast to other connected clients, each client receives an inbound message. For example, if 5 clients are connected to a channel and one client increments a counter: - 1 outbound message (from the client performing the increment) - 5 inbound messages (one delivered to each of the 5 connected clients, including the client that sent it) ## LiveMap operations Removing a key and setting a primitive value always sends one message: ```javascript // One message await myObject.get('settings').set('theme', 'dark'); // One message await myObject.get('settings').remove('theme'); ``` Creating a shallow `LiveMap` sends two messages: one to create the new `LiveMap` object, and one to assign it to the target object: ```javascript // Two messages: create map + assign to 'settings' await myObject.set('settings', LiveMap.create({ shallow: 'data' })); ``` Nested `LiveMap` or `LiveCounter` objects each generate their own creation messages: ```javascript // Four messages: // - create visits counter // - create stats map // - create settings map // - assign to 'settings' await myObject.set('settings', LiveMap.create({ stats: LiveMap.create({ visits: LiveCounter.create() }) })); ``` Batch operations result in a message for each operation included in the batch: ```javascript // Four messages await myObject.get('settings').batch((ctx) => { ctx.set('theme', 'dark'); ctx.set('fontSize', 14); ctx.set('notifications', true); ctx.remove('oldSetting'); }); ``` ## LiveCounter operations Incrementing and decrementing a counter always sends one message: ```javascript // One message await myObject.get('visits').increment(5); // One message await myObject.get('visits').decrement(3); ``` Creating a `LiveCounter` sends two messages: one to create the new `LiveCounter` object, and one to assign it to the target object: ```javascript // Two messages: create counter + assign to 'visits' await myObject.set('visits', LiveCounter.create(0)); ``` Creating a counter nested within a `LiveMap` also generates messages for the parent map: ```javascript // Four messages: // - create visits counter // - create stats map // - create settings map // - assign to 'settings' await myObject.set('settings', LiveMap.create({ stats: LiveMap.create({ visits: LiveCounter.create(0) }) })); ``` Batch operations result in a message for each operation included in the batch: ```javascript // Three messages await myObject.get('visits').batch((ctx) => { ctx.increment(5); ctx.increment(3); ctx.decrement(2); }); ``` ## Synchronization During initial synchronization and resynchronization, each object on the channel is sent as a message. For example, if a channel contains 10 objects (such as `LiveMap` and `LiveCounter` instances), a client attaching to the channel will receive 10 messages during synchronization. Similarly, if a client becomes disconnected and needs to resynchronize, it will receive messages for each object that needs to be synchronized. Only [reachable](https://ably.com/docs/liveobjects/concepts/objects#reachability) objects are counted. Ably may send [tombstone](https://ably.com/docs/liveobjects/concepts/objects#tombstones) objects to the client, but these will not count towards your usage. ## Subscriptions Subscribing to updates does not affect the number of messages received by a client. Any client attached to a channel with the `object-subscribe` capability automatically receives all object messages for that channel. Subscribing to updates on an object adds a listener that is called whenever the client receives updates for that object. ## REST API The [LiveObjects REST API](https://ably.com/docs/liveobjects/rest-api-usage) also counts messages for operations performed. When fetching objects via the REST API, each instance of an [object type](https://ably.com/docs/liveobjects/concepts/objects#object-types) included in the response is counted as one message. Each operation published via the REST API counts as one message. When creating objects using the `path` field, the server constructs two messages (a create operation and a `MAP_SET` operation to assign it).