---
title: "Metadata Module"
url: "https://radix-wiki.miow.me/contents/tech/core-concepts/metadata-module"
updated: 2026-10-03
description: "The Metadata module is one of the engine's pluggable object modules. Every globalized object – packages, components, resources, accounts – has a Metadata…"
---

# Metadata Module

| Layer | Object Module |
| --- | --- |
| [Blueprint](/contents/tech/core-concepts/blueprints-and-packages) name | `Metadata` |
| Type | Module |
| Methods | `create`, `create_with_data`, `set`, `lock`, `get`, `remove` |
| Roles | `metadata_setter`, `metadata_setter_updater`, `metadata_locker`, `metadata_locker_updater` |
| Value types | 16 scalar + 16 array forms |
| Defined in | `radix-engine (metadata module)` |
| Source | [radixdlt-scrypto](https://github.com/radixdlt/radixdlt-scrypto) |

## Introduction

The **Metadata module** is one of the engine's pluggable object modules. Every globalized object – packages, components, resources, accounts – has a Metadata module attached, exposing a typed key-value store for descriptive data: name, symbol, icon URL, description, tags, social links. Wallets, explorers, and dapps read metadata to render assets and components meaningfully. Writes are gated by [access rules](/contents/tech/core-concepts/access-rules-and-auth-zones) on the metadata role, so updates can be locked or restricted to specific [badges](/contents/tech/core-concepts/badges).

## Module interface

Metadata is attached to a globalized object rather than written by it, and the module exposes six methods, defined in [the metadata invocation definitions](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/object_modules/metadata/invocations.rs): `create` and `create_with_data` to attach the module (empty, or pre-populated in the same instruction), `set` and `remove` to write and delete a key, `get` to read one, and `lock` to freeze one.

`get` returns `Option` and `remove` returns a boolean saying whether a key was actually there — both are total, so reading metadata that was never set is a normal outcome rather than a failure. Because the module hangs off the object, a [blueprint](/contents/tech/core-concepts/blueprints-and-packages) does not have to declare fields for its own name and icon; the same interface serves [resources](/contents/tech/core-concepts/resources), [components](/contents/tech/core-concepts/components), packages, and [accounts](/contents/tech/core-protocols/smart-accounts) alike.

## Setting, and locking

The module declares [four roles](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/object_modules/metadata/roles.rs), deliberately separating the two powers: `metadata_setter` may write and remove keys, `metadata_locker` may freeze them, and `metadata_setter_updater` and `metadata_locker_updater` may reassign the respective role. An issuer can therefore keep the ability to correct a description while having already given up the ability to change a symbol — or hold the locker role in cold storage while a hot key handles routine updates.

`lock` takes a single key and is irreversible for that key: once locked, no role — including the owner — can set or remove it again. This is what lets a token's ticker or an [NFT](/contents/tech/core-protocols/nfts-on-radix) collection's name be a credible commitment rather than a promise, and it is why wallets and explorers can display a locked `symbol` without the qualification they would need for a mutable one. Locking is per key, so a resource can pin its identity while leaving its social links editable.

## Typed values

Metadata values are typed, not free-form strings. The [value discriminators](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/object_modules/metadata/models/discriminators.rs) enumerate 16 scalar forms — `String`, `Bool`, the integer widths, `Decimal`, `GlobalAddress`, `PublicKey` and `PublicKeyHash`, `NonFungibleGlobalId` and `NonFungibleLocalId`, `Instant`, `Url`, and `Origin` — each with a matching array form, for 32 in total.

The distinction between `Url` and `Origin` matters for the wallet: a dApp declares its definition account, and the origin it is served from, as typed metadata that the [Radix Wallet](/contents/tech/core-protocols/radix-wallet) can verify rather than merely render. A `GlobalAddress` value is a real reference the ledger can resolve, which is how dApp definitions and their components point at each other. Writes are gated by [access rules](/contents/tech/core-concepts/access-rules-and-auth-zones) on the metadata roles, so the whole structure is auditable state, not a display-layer convention.

## External Links

- [metadata module (radixdlt-scrypto)](https://github.com/radixdlt/radixdlt-scrypto/tree/main/radix-engine/src/object_modules/metadata)
- [metadata invocation definitions](https://github.com/radixdlt/radixdlt-scrypto/blob/main/radix-engine-interface/src/object_modules/metadata/invocations.rs)
- [Radix Docs: Metadata](https://docs.radixdlt.com/docs/metadata)
- [Radix Docs: Metadata for Wallet Display](https://docs.radixdlt.com/docs/metadata-for-wallet-display)
