BlogGetting Started with Hyperledger Fabric — Developer Guide 2025
Technical18 min readPublished 4 June 2025Updated 4 June 2026

Getting Started with Hyperledger Fabric — Developer Guide 2025

NB

Nitish Beejawat

Founder, Tantrija Enterprises

Share

Contents

  1. 1Hyperledger Fabric architecture: what makes it different
  2. 2Setting up your development environment
  3. 3Writing your first chaincode in Go
  4. 4Deploying chaincode to your development network
  5. 5Invoking and querying chaincode
  6. 6Common production patterns
  7. 7Next steps

Hyperledger Fabric is the most widely deployed enterprise blockchain platform globally. It powers supply chain networks tracking billions of dollars in goods, trade finance platforms processing letters of credit between major banks, and healthcare networks managing patient data across hospital systems. If you are building enterprise blockchain, you need to understand Fabric. This guide gets you from zero to a running development network with chaincode deployed.

Hyperledger Fabric architecture: what makes it different

Understanding Fabric's architecture before writing any code saves you from misunderstanding what you are building.

Fabric is not like Ethereum. There is no gas. There is no public token. The consensus model is fundamentally different. Here are the key concepts.

Organizations and MSP. Every participant in a Fabric network is an organization. Organizations are identified by X.509 certificates issued by their Certificate Authority (CA). The Membership Service Provider (MSP) handles this identity layer. In a three-bank consortium, each bank is an organization with its own MSP.

Peers. Each organization runs peer nodes that store ledger copies and execute chaincode. Peers can be endorsing peers (they execute and sign transaction proposals) or committing peers (they validate and write committed blocks).

Orderer. The ordering service provides consensus and creates the canonical order of transactions. In production Fabric, this is typically Raft-based. Orderers do not execute chaincode — they only order.

Channels. A channel is a private subnet within the Fabric network. Only channel members see channel transactions. This is the primary privacy mechanism. A consortium of five banks might have a single channel shared by all five for common data, plus bilateral channels between individual pairs for private bilateral transactions.

Chaincode. Smart contracts in Fabric are called chaincode. They run in Docker containers isolated from peer nodes. Chaincode is the application logic — what the ledger means and how it can be updated.

Endorsement policies. Unlike Ethereum where any transaction signed by the sender is valid, Fabric chaincode requires endorsement from specific peers before a transaction is committed. A typical policy might require "any two of three banks" to sign a transaction before it is considered endorsed.

Setting up your development environment

Prerequisites: Docker, Docker Compose, Go (1.21+), Node.js (18+), and Git.

Start by installing the Fabric binaries and Docker images. The Fabric team provides a bootstrap script:

curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh chmod +x install-fabric.sh ./install-fabric.sh docker binary

This pulls the Docker images for peers, orderers, and CAs, and installs the Fabric binaries (peer, orderer, configtxgen, cryptogen) to your PATH.

Clone the Fabric samples repository for reference:

git clone https://github.com/hyperledger/fabric-samples.git cd fabric-samples

The test-network directory contains a script to spin up a two-organization development network:

cd test-network ./network.sh up createChannel -c mychannel -ca

This starts two peer organizations (Org1 and Org2), creates a channel called mychannel, and uses CAs for certificate generation instead of the older cryptogen tool. When it completes you have a running Fabric network with a shared channel.

Writing your first chaincode in Go

Fabric chaincode can be written in Go, Java, or Node.js. Go is the production standard — it is faster, produces cleaner error messages, and has better tooling.

Create a directory for your chaincode:

mkdir -p chaincode/asset-transfer/go cd chaincode/asset-transfer/go

Initialize a Go module:

go mod init github.com/yourorg/asset-transfer

A minimal chaincode package looks like this:

package main

import ( "encoding/json" "fmt" "github.com/hyperledger/fabric-contract-api-go/contractapi" )

type AssetContract struct { contractapi.Contract }

type Asset struct { ID string "json:\"id\"" Owner string "json:\"owner\"" Value int "json:\"value\"" }

func (c *AssetContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, owner string, value int) error { exists, err := c.AssetExists(ctx, id) if err != nil { return err } if exists { return fmt.Errorf("asset %s already exists", id) } asset := Asset{ID: id, Owner: owner, Value: value} assetJSON, err := json.Marshal(asset) if err != nil { return err } return ctx.GetStub().PutState(id, assetJSON) }

func (c *AssetContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) { assetJSON, err := ctx.GetStub().GetState(id) if err != nil { return nil, fmt.Errorf("failed to read asset: %v", err) } if assetJSON == nil { return nil, fmt.Errorf("asset %s does not exist", id) } var asset Asset err = json.Unmarshal(assetJSON, &asset) if err != nil { return nil, err } return &asset, nil }

func (c *AssetContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) { assetJSON, err := ctx.GetStub().GetState(id) if err != nil { return false, fmt.Errorf("failed to read from world state: %v", err) } return assetJSON != nil, nil }

func main() { assetChaincode, err := contractapi.NewChaincode(&AssetContract{}) if err != nil { panic(fmt.Sprintf("Error creating chaincode: %v", err)) } if err := assetChaincode.Start(); err != nil { panic(fmt.Sprintf("Error starting chaincode: %v", err)) } }

Install the contract API library:

go get github.com/hyperledger/fabric-contract-api-go/contractapi

Deploying chaincode to your development network

The Fabric 2.x chaincode lifecycle requires a series of steps before chaincode goes live. This is more complex than Ethereum deployment but provides much better governance.

Step 1: Package the chaincode

cd ../../.. peer lifecycle chaincode package basic.tar.gz \ --path ./chaincode/asset-transfer/go \ --lang golang \ --label basic_1.0

This creates a chaincode package (basic.tar.gz) that can be installed on peers.

Step 2: Install on peers (must be done for each organization)

Set your environment variables for Org1:

export CORE_PEER_LOCALMSPID="Org1MSP" export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp export CORE_PEER_ADDRESS=localhost:7051

peer lifecycle chaincode install basic.tar.gz

Repeat with Org2 environment variables.

Step 3: Approve the chaincode definition (each organization must approve)

peer lifecycle chaincode approveformyorg \ --channelID mychannel \ --name basic \ --version 1.0 \ --package-id <PACKAGE_ID_FROM_INSTALL> \ --sequence 1 \ --tls \ --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

Step 4: Commit the chaincode definition

peer lifecycle chaincode commit \ --channelID mychannel \ --name basic \ --version 1.0 \ --sequence 1 \ --tls \ --cafile ... --peerAddresses localhost:7051 \ --peerAddresses localhost:9051

When commit succeeds, your chaincode is live on the channel.

Invoking and querying chaincode

With chaincode deployed, you can invoke transactions and query state.

Create an asset:

peer chaincode invoke \ -o localhost:7050 \ --ordererTLSHostnameOverride orderer.example.com \ --tls \ --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ -C mychannel \ -n basic \ --peerAddresses localhost:7051 \ --peerAddresses localhost:9051 \ -c '{"function":"CreateAsset","Args":["asset1","alice",100]}'

Query the asset (read-only, does not go through orderer):

peer chaincode query \ -C mychannel \ -n basic \ -c '{"function":"ReadAsset","Args":["asset1"]}'

This should return: {"id":"asset1","owner":"alice","value":100}

The key distinction: invoke creates a transaction that goes through endorsement → ordering → commit. Query executes locally on a peer and returns the result without creating a transaction.

Common production patterns

Development network and production network have different requirements. Here is what changes.

Certificate management. cryptogen is fine for development but must not be used in production. Use Fabric CA with proper certificate rotation policies. Each organization needs its own CA infrastructure with HSM-backed root keys in high-value deployments.

Ordering service sizing. A single orderer node is fine for development. Production requires a Raft cluster of at least three orderers for fault tolerance, ideally five for high availability.

Chaincode as an external service. In production, running chaincode as an external service (rather than in Docker containers managed by peers) gives you better performance, easier deployment, and the ability to run chaincode in environments where Docker-in-Docker is not available.

State database. Fabric supports LevelDB (default) and CouchDB for the state database. CouchDB enables rich queries using JSON selector syntax. If your chaincode needs complex queries across multiple fields, CouchDB is worth the operational overhead.

Private data collections. If specific data should only be shared between a subset of channel members, use private data collections. The hash of the private data is committed to the shared ledger; the data itself is stored only on the relevant peers.

Next steps

This guide has walked you through Fabric architecture, environment setup, chaincode development in Go, deployment through the Fabric lifecycle, and production patterns.

Where to go next: the Hyperledger Fabric documentation (hyperledger-fabric.readthedocs.io) is thorough and kept current. The fabric-samples repository contains more complex examples including private data collections, asset transfer with attribute-based access control, and off-chain data patterns.

For production deployments, the complexity grows significantly with the number of organizations, the sophistication of the privacy requirements, and the integration with enterprise systems. If you are building a production Fabric network as an enterprise blockchain development company India or globally, this is where experienced deployment support becomes valuable.

We have deployed production Fabric networks for financial services and supply chain clients. If you are scoping a Fabric deployment, book a strategy call — we can walk through your requirements and give you a realistic view of what production looks like.

NB

Nitish Beejawat

Founder, Tantrija Enterprises

Nitish Beejawat is the founder of Tantrija Enterprises and led core L1 protocol development on Layer One X — a custom Layer 1 blockchain built from scratch. He has 6+ years of production blockchain engineering experience across DeFi, enterprise blockchain, and custom chain development.

linkedin.com/in/nitish-beejawat
/ Get Started

Building a production Hyperledger Fabric network?

We have deployed Fabric in production. Book a strategy call and we will walk through your specific requirements.

No sales pitch. Just an honest technical conversation.