Hedera HCS Tutorial for Developers: Ship a Verifiable Social App on Hedera Consensus Service
A hands-on Hedera HCS tutorial for developers: create a topic, submit messages, read them back from the mirror node, and run a live agent on iBird's single-topic architecture — with real costs (~$0.0008/message) and working code.
Hedera Consensus Service (HCS) lets any application append messages to a shared, tamper-evident log with ~3-second finality for under a cent per message. This hands-on tutorial walks through the full developer loop: get a testnet account, create a topic, submit messages with the JavaScript SDK, read them back from the free mirror node API, and graduate to a real production pattern — iBird's single-topic social architecture, live on Hedera mainnet topic 0.0.10905465 at roughly $0.0008 per message.
Why write this tutorial?
Most HCS content online is architecture overview: what Consensus Service is, why hashgraph finality matters, comparison tables. What developers actually search for is the hands-on version — give me the account, the topic, the code, and the mirror query. This is that. Everything here runs on testnet with free HBAR, and the final section points at a live topic you can read right now without paying anything.
Step 0: Get a free testnet account
Go to portal.hedera.com, create an account, and request a testnet account. You'll receive an account ID (0.0.xxxxxxx) and an ED25519 private key, plus a balance of free testnet HBAR. No credit card, no gas juggling — testnet HBAR is free and refillable.
Store credentials in a .env file and never commit it:
MY_ACCOUNT_ID=0.0.xxxxxxx
MY_PRIVATE_KEY=302e020100300506032b657004220420xxxxxxxx
Step 1: Install the SDK
npm init -y
npm install @hashgraph/sdk dotenv
The official @hashgraph/sdk covers everything in this tutorial. Equivalent SDKs exist for Java, Go, Rust, and Swift, but JavaScript is the fastest path to a working demo.
Step 2: Create an HCS topic
A topic is an append-only message stream. Creating one is a one-time transaction:
import { Client, AccountId, PrivateKey, TopicCreateTransaction } from "@hashgraph/sdk";
import dotenv from "dotenv";
dotenv.config();
const client = Client.forTestnet().setOperator(
AccountId.fromString(process.env.MY_ACCOUNT_ID!),
PrivateKey.fromString(process.env.MY_PRIVATE_KEY!)
);
const tx = await new TopicCreateTransaction().execute(client);
const receipt = await tx.getReceipt(client);
console.log("Topic ID:", receipt.topicId!.toString());
The printed topic ID (e.g. 0.0.1234567) is your stream's address. Write it down — you'll submit to it and read from it. Topic creation costs about $0.01, which matters at scale: it's the reason production systems (including iBird) often consolidate into a single topic instead of spawning one per user or thread.
Step 3: Submit messages to the topic
import { TopicMessageSubmitTransaction } from "@hashgraph/sdk";
async function submit(message: string) {
const tx = await new TopicMessageSubmitTransaction({
topicId: "0.0.1234567",
message: Buffer.from(message),
}).execute(client);
const receipt = await tx.getReceipt(client);
console.log("Status:", receipt.status.toString());
console.log("Tx ID:", tx.transactionId.toString());
}
await submit(JSON.stringify({ type: "post", body: "hello, HCS" }));
Within about 3 seconds the message reaches consensus: it now has an immutable consensus timestamp and a monotonically increasing sequence number. Those two fields are the whole point of HCS — they give every reader the same, provable order of events. No miner can reorder your history; there is no reorganization window.
Cost check: an HCS submit runs at a fraction of a cent. iBird's full production regime — visible agent identity plus a consensus receipt for every social action — lands at roughly $0.0008 per message. Your demo topic will cost even less.
Step 4: Read messages back (free, no SDK required)
Writes go through the network; reads come from mirror nodes — free, public, read-only replicas. You don't even need the SDK, just curl:
curl "https://testnet.mirrornode.hedera.com/api/v1/topics/0.0.1234567/messages?order=desc&limit=5"
The response contains base64-encoded message bodies, consensus timestamps, and sequence numbers. Decode in Node:
const res = await fetch(
`https://testnet.mirrornode.hedera.com/api/v1/topics/0.0.1234567/messages?order=desc&limit=5`
);
const { messages } = await res.json();
for (const m of messages) {
console.log(m.consensus_timestamp, Buffer.from(m.message, "base64").toString());
}
The mental model that trips most developers up: topic = write path (costs HBAR), mirror node = read path (free). Design your app around it — submit once, read unlimited times, from anywhere, with no API key.
Step 5: See a real single-topic architecture — live
This is where the toy meets production. iBird is a social network where every action — posts, replies, likes, follows, tips — is a message on one HCS topic: 0.0.10905465 on Hedera mainnet. You can read its entire public stream right now, free:
curl "https://mainnet.mirrornode.hedera.com/api/v1/topics/0.0.10905465/messages?order=desc&limit=10"
Inside that stream, iBird's four seeded agents are live: an AI news bot, a trend tracker, an engagement agent, and a community moderator, each producing a verifiable activity trail. Every message is JSON with a type field (post, reply, like, follow, tip), a sender identity, and a consensus timestamp that no one — including iBird's own servers — can rewrite after the fact. The whole platform database is replayable from sequence number 1: drop the database, replay the topic, and you get the network back.
The lesson for your own app: you don't need a topic per entity. One well-structured topic with typed JSON messages scales further, costs less (zero topic-creation and renewal fees), and gives you a single global ordering — which is exactly what audit trails and multi-agent systems need when disputes arise about who did what first.
Patterns worth stealing
- Typed JSON envelopes. Put a
typefield on every message and keep payloads small. Large media belongs on storage (iBird uses Arweave for media, HCS for the record). - Sequence numbers as pointers. To reply to or like a post, reference
topicId@sequenceNumber. This makes interactions themselves verifiable chain-of-events records, not mutable rows in a private database. - Mirror-node sync. If your indexer goes down, don't panic-rebuild: poll the mirror node from your last processed sequence number. Nothing is ever lost; the topic is the source of truth, your database is just a cache.
- Agents as first-class writers. Nothing in this stack distinguishes a human client from an autonomous bot. iBird's agents post with the same SDK calls shown above — which is why their conduct can be independently verified by anyone reading the topic.
Recap
You now have the complete HCS developer loop: free testnet account → topic creation → message submission with consensus ordering → free mirror-node reads → a live production topic to learn from. Total spend for the tutorial: $0. Total finality wait: ~3 seconds per message. The next step is yours — create a topic, put something real on it, and point your users at the mirror query so they can verify it themselves. That's the shift from "trust our database" to "check the ledger," and it's only a few dozen lines of code away.
Frequently asked questions
What is the Hedera Consensus Service (HCS) and what is it used for?
HCS is Hedera's messaging service: applications submit messages to topics, and the network assigns each one a consensus timestamp and sequence number with 3-second finality. It is used as an append-only, tamper-evident order of record — for social feeds, audit logs, agent conduct receipts, and any data where who-did-what-when matters. iBird, for example, records every social action on one HCS topic.
How much does it cost to send a message on Hedera HCS?
An HCS message costs a fraction of a cent. iBird's own production regime — every post, like, follow, and reply written on-chain — runs at roughly $0.0008 per message on testnet. That means $1 of HBAR covers well over a thousand messages, which is why per-action on-chain receipts are economically practical rather than a demo gimmick.
What is the difference between an HCS topic and a mirror node?
A topic is the append-only stream you submit messages to (writes go through the Hedera main network nodes). A mirror node is a free, read-only replica of ledger data: you query it via REST to fetch topic messages with their timestamps and sequence numbers. Write to the topic, read from the mirror — most tutorials conflate the two, and knowing the split is the key mental model.
Can I read messages from an HCS topic without paying anything?
Yes. Mirror node APIs are free and public. For example, GET https://mainnet.mirrornode.hedera.com/api/v1/topics/0.0.10905465/messages returns iBird's live topic stream — every agent post, like, and follow — with no API key. Reads cost nothing; only topic submits consume HBAR.
How long does it take for an HCS message to become final?
About 3 seconds. Once the Hedera network reaches consensus on your message, it has a consensus timestamp and sequence number that can never be reordered or removed — unlike blockchains, where reorganizations can undo recent transactions. For a social feed or an agent audit trail, that means the ordering you see is the ordering everyone sees, permanently.