Key Principle
"A DApp is an application that is mostly or entirely decentralized." Smart contracts decentralize logic and payment; web3 extends decentralization to everything else. A DApp spans five aspects, each independently sliding centralized↔decentralized: (1) backend logic, (2) frontend, (3) storage, (4) messaging, (5) name resolution. A DApp is only as decentralized as its least decentralized component — the weakest-link principle. Ship "unstoppable" contracts behind a takedownable web host and the whole app is takedownable; the censorship-resistance of the contract layer is wasted. [DATED 2018]
Why This Matters
On-chain execution is bounded by gas and a low block gas limit, so "smart contracts are not well suited to storing or processing large amounts of data." The EVM is where you put only the logic that must be trustless and deterministic; everything bulky (images, video, the frontend HTML/CSS/JS itself) is pushed off-chain. A DApp is therefore a layered stack, not a monolithic on-chain program. Many apps misnamed "DApps" are centralized "CApps" — the taxonomy exists so you can locate where trust actually lives.
DApp advantages derive from blockchain properties: resiliency (backend on-chain, no downtime while the platform runs), transparency (code publicly inspectable, interactions stored forever), censorship resistance (reach any Ethereum node → interact; no provider or owner can alter deployed code).
Smart-contract backend constraints force off-chain design: computation is very expensive (keep on-chain logic minimal); code is immutable after deploy — it "can be deleted if it is programmed with an accessible SELFDESTRUCT opcode, but other than complete removal, the code cannot be changed in any way." Immutability is censorship resistance, but bugs can't be patched — demanding defensive programming up front.
Good Examples
Off-chain content-addressable storage — IPFS / Swarm. Both are content-addressable: the file's hash is its identifier, so "you retrieve any file from any node by requesting it by its hash." This replaces HTTP's server-centric model — no origin server to take down or trust. Gas makes on-chain storage prohibitively expensive; a centralized file server is a censorship chokepoint; Swarm/IPFS resolves both. Because resources reference each other by URL, you must npm run build to package cross-references into a self-contained dist/, then upload recursively with a default entry path (index.html), replicating the web server's index behavior.
Whisper messaging — decentralized IPC over P2P (per-auction encrypted chat rooms); removes the central message-server dependency. With Swarm storing both resources and the frontend files, Whisper handling chat, and ENS naming the frontend, the Auction DApp removes every server dependency: omit any layer and a central failure point returns.
Auction DApp stack (worked example) — six parts: (1) DeedRepository (ERC721 "deed" tokens for unique assets); (2) AuctionRepository (auction logic, "cannot be stopped, nor can any auction be controlled"); (3) Vue/Vuetify frontend; (4) web3.js via MetaMask (the only Ethereum-specific seam is in-browser key management + signing); (5) Swarm for images and the frontend; (6) Whisper for chat. Flow: register deed → ownership transfers to DApp → listed → others bid → finalize → deed transfers to winner.
ENS (Ethereum Name Service) — resolves human-readable names (ethereum.eth → an address) to addresses, content hashes, and resources, with no central authority that can seize or censor. The usability layer for self-custody.
- Namehash collapses a name to a fixed 32-byte "node" recursively, so lookup is O(1) and can be precomputed off-chain — no on-chain string work:
namehash([]) = 0x00...00(32 zero bytes);namehash([label, ...]) = keccak256(namehash(...) + keccak256(label)). - "Sandwich" architecture — fund safety from structure, not audits: bottom = minimal base registry (ERC137, <50 lines); middle = registrar/auction (>500 lines, "where the early development efforts (and bugs!)" live), made replaceable; top = fund custody in separate accounts. The complex layer is swappable; funds are quarantined above it.
- Registry → resolver two-step resolution (survived the 2019 redesign): hash the name, call the registry → returns the resolver address; call the resolver → returns the resource. Decouples naming from resource semantics — new resource types need no registry change.
- Modified-Vickrey auction + per-name deed (historical): sealed bids, winner pays second-highest bid, adapted for a public chain via lock-funds-upfront, commit–reveal ("you can't hide secrets on a blockchain"), and reveal-or-forfeit. Per-name ~50-line deed contracts locked funds (recoverable by selling back) rather than concentrating funds — "having a single contract hold millions of dollars in ether has proven to be very risky."
Counterpoints
Governance — the unavoidable, no-safe-default trade-off. A DApp must choose between privileged admin accounts and full autonomy; both failure modes are real:
- Admin keys → bug-recovery possible, but the key is a single point of compromise. "Bancor was not as decentralized as initially assumed" — a compromised management account enabled a massive theft.
- No admin keys → genuinely decentralized, but no recourse. The DAO's "curator" accounts could not override the attacker's withdrawal.
Author's verdict: "true DApps cannot have specialized access for privileged accounts — that's not decentralized." Progressive decentralization means removing every server dependency; omit any layer and a central failure point returns.
Key Quotes
"A DApp is an application that is mostly or entirely decentralized." — Antonopoulos & Wood, Chapter 12
"Are we forced to sacrifice usability in order to gain decentralization? Not necessarily." — Antonopoulos & Wood, Chapter 12
"Having a single contract hold millions of dollars in ether has proven to be very risky." — Antonopoulos & Wood, Chapter 12
Rules of Thumb
- Audit the whole stack: a DApp is only as decentralized as its least-decentralized layer.
- Push bulky data (images, frontend files) to content-addressable storage (IPFS/Swarm); keep on-chain logic minimal.
- Serve the frontend itself from decentralized storage, not a takedownable web host; build then upload recursively with a default
index.html. - Use ENS to map a human name to a content hash; restore usability without recentralizing.
- Decide governance deliberately: admin keys reintroduce a trusted intermediary; no admin keys means defensive programming is your only defense.
- Note ENS spec EIPs: EIP-137 (core), EIP-162 (
.ethauction, now superseded), EIP-181 (reverse resolution); the root node was held by a 4-of-7 multisig meant to dissolve over time. [DATED 2018]: Swarm spun out of the EF (IPFS now dominant); Whisper→Waku/libp2p pubsub; the ENS auction/deed model was replaced in 2019 by a permanent rental registrar (annual fees). Registry→resolver resolution and namehash remain current.
Related References
- EVM Internals — Stack Machine, State, Gas, and Bytecode - gas/immutability constraints that force off-chain components
- Oracles — Importing Trusted Data into a Deterministic EVM - off-chain data dependency re-imports the oracle problem
- Smart Contract Vulnerability Catalog - admin keys (Bancor) and SELFDESTRUCT
- Tokens (ERC-20, ERC-721, Fungibility, Standards) - ERC721 deeds used in the Auction DApp