Skip to main content

Manage DNS records (advanced interface mode with dynamic response)

CDB Managed DNS advanced interface mode allows creating DNS record sets (RRSets) with dynamic response — routing DNS responses based on geography, weight, latency, or health checks.

Create a DNS record

  1. 1

    Select a DNS zone

    Navigate to All zones and select the zone to which records should be added. Alternatively, click the three-dot icon on the right and select Go to records.

    All zones list with a DNS zone ready to open

    Check that the Advanced toggle in the Interface mode section is enabled (green):

    Zone records page with the Advanced interface mode toggle enabled
  2. 2

    Open the record creation form

    Click Add record set.

    Zone records in advanced mode with the Add record set button

    A new page opens with the record creation form.

    Add record form with Type, Name, TTL, Dynamic response, and Records fields
  3. 3

    Select the record type

    In the Type field, select the DNS record type: A, AAAA, NS, CNAME, MX, SRV, HTTPS, TXT, CAA, or SVCB. Each type is described in DNS records.

  4. 4

    Set the record name

    In the Name field, specify the subdomain the record belongs to. The options are:

    • Leave the field blank to add a record for the apex domain (sample-test.com).
    • Enter a subdomain name to add a record for that subdomain. Entering one creates a record for one.sample-test.com.
    • Enter an asterisk (*) to add a wildcard record that applies to all subdomains.
  5. 5

    Set the TTL

    In the TTL field, specify the TTL (time to live) in seconds.

  6. 6

    Configure dynamic response (optional)

    The dynamic response feature is available on the Free plan, but creating more than one dynamic RRset requires a paid plan.

    CDB's DNS servers can return different DNS records to different users — users in Asia can be directed to an Asian server and users in Europe to a European one. This is called dynamic response. Full configuration instructions are in dynamic response.

    To enable dynamic response, check the Dynamic response checkbox. Leave it unchecked to proceed without dynamic response.

  7. 7

    Set the record value status

    Each record value is active by default. To save a value without activating it, uncheck the toggle next to that record.

  8. 8

    Enter the record value

    In the Content field, enter a value for the record type.

  9. 9

    Add metadata (optional)

    Specify associated metadata to be used for dynamic response configuration. The metadata guide covers the full configuration.

  10. 10

    Add more record values (optional)

    Click Add record to specify additional values for the record set. A new record entry appears — enter the content and metadata as needed. To remove a record value, click the minus button next to it. To disable a value without removing it, uncheck its toggle.

  11. 11

    Create the record

    Click Create.

    The record set is created with the specified parameters. Use the DNS Lookup tool to verify that the record resolves with the expected values.

Manage a DNS record

  1. 1

    Select a DNS zone

    Navigate to All zones and select the zone containing the records to edit or delete.

    All zones list with a DNS zone ready to open
  2. 2

    Edit or delete a record

    Zone records list with the three-dot menu showing Edit record and Delete options

    Edit a record: Click the record name or select Edit record from the three-dot menu. Change the required values and click Save.

    Delete a record: Open the three-dot menu and select Delete.

The DNS API manages record sets (RRsets) using POST, GET, PUT, and DELETE requests. Advanced interface mode enables dynamic response: pickers control which records are returned based on per-record metadata such as weight, countries, or continents. Full picker and selector options are documented in the dynamic response guide.

The code samples below use an A record. To work with another supported type (AAAA, CNAME, MX, TXT, and others), replace A with the required RRset type and provide the corresponding record content.

An API token is required.

Open a terminal and export the required variables:

export GCORE_API_KEY="{YOUR_API_KEY}"
export ZONE_NAME="{YOUR_ZONE_NAME}"        # e.g. example.com
export RECORD_NAME="{YOUR_RECORD_NAME}"    # e.g. app.example.com

Create a record

Creating an RRset with pickers enables dynamic response. The two-picker chain below applies weighted probability to distribute traffic and then limits the response to a single record: weighted_shuffle assigns each record a relative probability proportional to its weight, and first_n with limit: 1 selects one record from the shuffled list. Omit the pickers field to create a static record that always returns all values.

import os
from gcore import CDB

client = CDB()

rrset = client.dns.zones.rrsets.create(
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    rrset_type="A",
    ttl=300,
    resource_records=[
        {"content": ["1.2.3.4"], "meta": {"weight": 10}},
        {"content": ["5.6.7.8"], "meta": {"weight": 5}},
    ],
    pickers=[
        {"type": "weighted_shuffle"},
        {"type": "first_n", "limit": 1},
    ],
)
print(rrset.name, rrset.type, [p.type for p in (rrset.pickers or [])])
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    rrset, err := client.DNS.Zones.Rrsets.New(ctx, "A", dns.ZoneRrsetNewParams{
        ZoneName:  os.Getenv("ZONE_NAME"),
        RrsetName: os.Getenv("RECORD_NAME"),
        Ttl:       gcore.Int(300),
        ResourceRecords: []dns.ZoneRrsetNewParamsResourceRecord{
            {Content: []any{"1.2.3.4"}, Meta: map[string]any{"weight": 10}},
            {Content: []any{"5.6.7.8"}, Meta: map[string]any{"weight": 5}},
        },
        Pickers: []dns.ZoneRrsetNewParamsPicker{
            {Type: "weighted_shuffle"},
            {Type: "first_n", Limit: gcore.Int(1)},
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("created: %s %s pickers:%d\n", rrset.Name, rrset.Type, len(rrset.Pickers))
}
curl -X POST "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/$RECORD_NAME/A" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ttl": 300,
    "resource_records": [
      {"content": ["1.2.3.4"], "meta": {"weight": 10}},
      {"content": ["5.6.7.8"], "meta": {"weight": 5}}
    ],
    "pickers": [
      {"type": "weighted_shuffle"},
      {"type": "first_n", "limit": 1}
    ]
  }'

The API returns:

{
  "name": "app.example.com",
  "type": "A",
  "ttl": 300,
  "pickers": [
    {"type": "weighted_shuffle", "strict": false},
    {"type": "first_n", "limit": 1, "strict": false}
  ],
  "resource_records": [
    {"id": 1001, "content": ["1.2.3.4"], "enabled": true, "meta": {"weight": 10}},
    {"id": 1002, "content": ["5.6.7.8"], "enabled": true, "meta": {"weight": 5}}
  ]
}

List records

Returns all RRsets in a zone, including their type, TTL, and pickers. Use this to locate an RRset when its name or type is unknown before retrieving or editing it.

import os
from gcore import CDB

client = CDB()

result = client.dns.zones.rrsets.list(zone_name=os.environ["ZONE_NAME"])
print("total:", result.total_amount)
for r in result.rrsets or []:
    print(r.name, r.type, "pickers:", [p.type for p in (r.pickers or [])])
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    result, err := client.DNS.Zones.Rrsets.List(ctx, os.Getenv("ZONE_NAME"), dns.ZoneRrsetListParams{})
    if err != nil {
        panic(err)
    }
    fmt.Println("total:", result.TotalAmount)
    for _, r := range result.Rrsets {
        fmt.Printf("  %s %s pickers:%d\n", r.Name, r.Type, len(r.Pickers))
    }
}
curl "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/rrsets" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns:

{
  "rrsets": [
    {
      "name": "app.example.com",
      "type": "A",
      "ttl": 300,
      "pickers": [
        {"type": "weighted_shuffle", "strict": false},
        {"type": "first_n", "limit": 1, "strict": false}
      ]
    }
  ],
  "total_amount": 1
}

Get a record

Returns the full RRset including all resource records and their metadata. Retrieve the current state before editing to preserve existing values that should not change.

import os
from gcore import CDB

client = CDB()

rrset = client.dns.zones.rrsets.get(
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    rrset_type="A",
)
print(rrset.name, "ttl:", rrset.ttl, "records:", len(rrset.resource_records or []))
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    rrset, err := client.DNS.Zones.Rrsets.Get(ctx, "A", dns.ZoneRrsetGetParams{
        ZoneName:  os.Getenv("ZONE_NAME"),
        RrsetName: os.Getenv("RECORD_NAME"),
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("%s ttl:%d records:%d\n", rrset.Name, rrset.Ttl, len(rrset.ResourceRecords))
}
curl "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/$RECORD_NAME/A" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns:

{
  "name": "app.example.com",
  "type": "A",
  "ttl": 300,
  "pickers": [
    {"type": "weighted_shuffle", "strict": false},
    {"type": "first_n", "limit": 1, "strict": false}
  ],
  "resource_records": [
    {"id": 1001, "content": ["1.2.3.4"], "enabled": true, "meta": {"weight": 10}},
    {"id": 1002, "content": ["5.6.7.8"], "enabled": true, "meta": {"weight": 5}}
  ]
}

Edit a record

PUT fully replaces the RRset — all existing resource records and pickers are overwritten. Fetch the current state first (see Get a record), then submit the complete updated body.

import os
from gcore import CDB

client = CDB()

rrset = client.dns.zones.rrsets.replace(
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    rrset_type="A",
    ttl=600,
    resource_records=[
        {"content": ["1.2.3.4"], "meta": {"weight": 20}},
        {"content": ["5.6.7.8"], "meta": {"weight": 5}},
    ],
    pickers=[
        {"type": "weighted_shuffle"},
        {"type": "first_n", "limit": 1},
    ],
)
print("updated ttl:", rrset.ttl)
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    rrset, err := client.DNS.Zones.Rrsets.Replace(ctx, "A", dns.ZoneRrsetReplaceParams{
        ZoneName:  os.Getenv("ZONE_NAME"),
        RrsetName: os.Getenv("RECORD_NAME"),
        Ttl:       gcore.Int(600),
        ResourceRecords: []dns.ZoneRrsetReplaceParamsResourceRecord{
            {Content: []any{"1.2.3.4"}, Meta: map[string]any{"weight": 20}},
            {Content: []any{"5.6.7.8"}, Meta: map[string]any{"weight": 5}},
        },
        Pickers: []dns.ZoneRrsetReplaceParamsPicker{
            {Type: "weighted_shuffle"},
            {Type: "first_n", Limit: gcore.Int(1)},
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("updated ttl:%d pickers:%d\n", rrset.Ttl, len(rrset.Pickers))
}
curl -X PUT "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/$RECORD_NAME/A" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ttl": 600,
    "resource_records": [
      {"content": ["1.2.3.4"], "meta": {"weight": 20}},
      {"content": ["5.6.7.8"], "meta": {"weight": 5}}
    ],
    "pickers": [
      {"type": "weighted_shuffle"},
      {"type": "first_n", "limit": 1}
    ]
  }'

The API returns the updated RRset with the same structure as the create response.

Delete a record

Removes the RRset and all its resource records permanently.

import os
from gcore import CDB

client = CDB()

client.dns.zones.rrsets.delete(
    zone_name=os.environ["ZONE_NAME"],
    rrset_name=os.environ["RECORD_NAME"],
    rrset_type="A",
)
print("deleted")
package main

import (
    "context"
    "fmt"
    "os"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/dns"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()

    _, err := client.DNS.Zones.Rrsets.Delete(ctx, "A", dns.ZoneRrsetDeleteParams{
        ZoneName:  os.Getenv("ZONE_NAME"),
        RrsetName: os.Getenv("RECORD_NAME"),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("deleted")
}
curl -X DELETE "https://api.cdb-staging.cdn.orange.com/dns/v2/zones/$ZONE_NAME/$RECORD_NAME/A" \
  -H "Authorization: APIKey $GCORE_API_KEY"

The API returns HTTP 200 with an empty body on success.