Go: How to store demo health-data in immudb

Gophers are not made for being locked down. Luckily the pandemic is about to end as multiple promising vaccines will be released soon. Once again innovation is the key to success. In order to minimize the damage to economies and well-being, we have to outsmart the virus by using the latest technology. Unfortunately, yellow cards (certificate of vaccination) are relicts of the 19 th century. I lost my yellow card some years ago, most entries were bleached out anyways. This is not a proper tool for today’s situation. I wished my vaccination data was stored safely, immutable, and verifiable like in immudb. Immudb is an open-source, lightweight, high-speed immutable database with built-in cryptographic proof and verification. Much smarter technology than paper cards and surprisingly easy to use. In fact it takes just some minutes. This Blog is about how to store data in immudb using every gopher’s favorite programming language: Go.

How to store demo health data in immudb (tutorial)

How does vaccination data look like? The following data model is inspired by the international Health Level 7 standard but strongly simplified. First, we need the personal data of the patient. Every person has a unique identification value, a name, and a date of birth:

Person identification name date_of_birth
1 345623 Smarty McGopher 20/10/1980

Every person can get multiple vaccinations. Each vaccination has a manufacturer, a substance and product_id for identifying the charge, date of vaccination, and the id of the doctor who supervised the vaccination:

Vaccination manufacturer substance product_id date_of_vaccination doctor_id
1 Vaccine int. corp IPV 1230 15/09/2012 345231
2 Medco HEPB 3309 03/06/2015 345231
3 Gopher Immunization inc. COV19 1097 15/03/2021 345231

Immudb is able to store key-value pairs. In order to use immudb for our demo vaccination data, we have to transform it into that schema.

key (identification:valuename) value
345623:name Smarty McGopher
345623:date_of_birth 20/10/1980

Let’s join the vaccination information with the personal data:

key (identification.person:substance.vaccination:valuename value
345623:IPV:manufacturer Vaccine int. corp
345623:HEPB:manufacturer Medco
345623:COV19:manufacturer Gopher Immunization inc.
345623:IPV:date_if_vaccination 15/09/2012
345623:HEPB:date_if_vaccination 03/06/2015
345623:COV19:date_if_vaccination 15/03/2021
345623:IPV:doctor_id 100234
345623:HEPB:doctor_id 100234
345623:COV19:doctor_id 100956
345623:IPV:product_id 1230
345623:HEPB:product_id 3309
345623:COV19:product_id 1097

The keys in immudb are not unique, which means you can set them again and if you request the value of the key you will get back the most recent value. Internally each key has an own table and you can trace the changes through a history function. You can also set a JSON object as the value of a key. For example, we could transform the vaccinations of Smarty McGopher into a JSON structure and save multiple vaccinations by using only one key. The downside of that is that we have to get all vaccinations and add the latest when he is vaccinated again.

Let’s look at the code

We are using Google’s Golang in this tutorial. However, immudb supports a whole lot of languages and there is also a REST-interface available by using immugw.

First we need to get immudb and run it. It takes just some seconds using this jumpstart guide. Next, we connect through the immuclient to immudb. The default options will use your local IP address and port 3322. The default user is immudb and the default password also immudb. Look up the full code on github.

client, err := immuclient.NewImmuClient(immuclient.DefaultOptions())
ctx := context.Background()
// login with default username and password
lr, err := client.Login(ctx, []byte(`immudb`), []byte(`immudb`))

We are now logged in. Immudb provides multi-database capabilities, that’s why we can create a new database. Let’s call it “yellowcard” (remember you can only create a database with that name once). We also have to switch to that database in order to use it. The switch is being done by the token, as it is not only used for authentication, but also to route calls to the correct database.

err = client.CreateDatabase(ctx, &schema.Database{
    Databasename: "yellowcard",
    // switch to database
resp, err := client.UseDatabase(ctx, &schema.Database{
    Databasename: "yellowcard",
md = metadata.Pairs("authorization", resp.Token)
ctx = metadata.NewOutgoingContext(context.Background(), md)

Having switched to our database, we are now ready to set our data. Golang provides a great datatype for the key-value schema called map. A map is filled by a key and it’s the corresponding value. The type of the value is being set when defining a map. Immudb loves bytes so we choose bytes.

// key-value map for personal data
person := map[string][]byte{            "345623:name": []byte("Smarty McGopher"),
                                        "345623:date_of_birth":  []byte("20/10/1980")}
// key-value map for vaccination data
vaccinations := map[string][]byte{      "345623:IPV:manufacturer": []byte("Vaccine int. corp"),
                                        "345623:HEPB:manufacturer" : []byte("Medco"),
                                        "345623:COV19:manufacturer": []byte("Gopher Immunization inc."),
                                        "345623:IPV:date_if_vaccination": []byte("15/09/2012"),

This looks already pretty good, we could now already set the key-value pairs in immudb. However Smarty McGopher wants full control over his data, that’s why he decides to encrypt the values using his password.

var password = "SmartyMcGopherisSmart-and-encrypts!#vaccinationdata!"
//create a new map with encrypted values
var encryptedPersonMap map[string][]byte=encryptMapValues(person,password,randomSalt(10))
var encryptedVaccinationMap map[string][]byte=encryptMapValues(vaccinations,password,randomSalt(10))

This looks good. Now we can iterate over the keys of the maps and write verifiably in immudb! You can write and read with built-in cryptographic verification. Also, we can read values by querying for the key, but of course, they are encrypted. We have to decrypt them first to be able to read them.

// sets key-values of map in immudb
for key, value := range encryptedPersonMap {
    if _, err := client.VerifiedSet(ctx, []byte(key), value); err != nil {
for key := range encryptedPersonMap {
    if item, err := client.Get(ctx, []byte(key)); err != nil {
    } else {
        // immudb sdk provides structured data.
        fmt.Printf("%sn", decryptValue(item.Value, password, randomSalt(10)))

Our Gopher’s vaccination data is now verifiable and immutably stored in immudb. Today’s challenges need technology like immudb to make the world a better place again. Smarty McGopher could now easily and safely proof his vaccinations and travel again. There are many more features of immudb that will be discussed in future blogs like adding references and indexes to data.
Keep track of immudb by leaving a star at



Open Source and easy to use in new applications and easy to integrate into existing application.

Subscribe to Our Newsletter

Get the latest product updates, company news, and special offers delivered right to your inbox.

Subscribe to our newsletter

Use Case - Tamper-resistant Clinical Trials


Blockchain PoCs were unsuccessful due to complexity and lack of developers.

Still the goal of data immutability as well as client verification is a crucial. Furthermore, the system needs to be easy to use and operate (allowing backup, maintenance windows aso.).


immudb is running in different datacenters across the globe. All clinical trial information is stored in immudb either as transactions or the pdf documents as a whole.

Having that single source of truth with versioned, timestamped, and cryptographically verifiable records, enables a whole new way of transparency and trust.

Use Case - Finance


Store the source data, the decision and the rule base for financial support from governments timestamped, verifiable.

A very important functionality is the ability to compare the historic decision (based on the past rulebase) with the rulebase at a different date. Fully cryptographic verifiable Time Travel queries are required to be able to achieve that comparison.


While the source data, rulebase and the documented decision are stored in verifiable Blobs in immudb, the transaction is stored using the relational layer of immudb.

That allows the use of immudb’s time travel capabilities to retrieve verified historic data and recalculate with the most recent rulebase.

Use Case - eCommerce and NFT marketplace


No matter if it’s an eCommerce platform or NFT marketplace, the goals are similar:

  • High amount of transactions (potentially millions a second)
  • Ability to read and write multiple records within one transaction
  • prevent overwrite or updates on transactions
  • comply with regulations (PCI, GDPR, …)


immudb is typically scaled out using Hyperscaler (i. e. AWS, Google Cloud, Microsoft Azure) distributed across the Globe. Auditors are also distributed to track the verification proof over time. Additionally, the shop or marketplace applications store immudb cryptographic state information. That high level of integrity and tamper-evidence while maintaining a very high transaction speed is key for companies to chose immudb.

Use Case - IoT Sensor Data


IoT sensor data received by devices collecting environment data needs to be stored locally in a cryptographically verifiable manner until the data is transferred to a central datacenter. The data integrity needs to be verifiable at any given point in time and while in transit.


immudb runs embedded on the IoT device itself and is consistently audited by external probes. The data transfer to audit is minimal and works even with minimum bandwidth and unreliable connections.

Whenever the IoT devices are connected to a high bandwidth, the data transfer happens to a data center (large immudb deployment) and the source and destination date integrity is fully verified.

Use Case - DevOps Evidence


CI/CD and application build logs need to be stored auditable and tamper-evident.
A very high Performance is required as the system should not slow down any build process.
Scalability is key as billions of artifacts are expected within the next years.
Next to a possibility of integrity validation, data needs to be retrievable by pipeline job id or digital asset checksum.


As part of the CI/CD audit functionality, data is stored within immudb using the Key/Value functionality. Key is either the CI/CD job id (i. e. Jenkins or GitLab) or the checksum of the resulting build or container image.

White Paper — Registration

We will also send you the research paper
via email.

CodeNotary — Webinar

White Paper — Registration

Please let us know where we can send the whitepaper on CodeNotary Trusted Software Supply Chain. 

Become a partner

Start Your Trial

Please enter contact information to receive an email with the virtual appliance download instructions.

Start Free Trial

Please enter contact information to receive an email with the free trial details.