Hostname seperti demo.instara.app dapat mencapai Cloudflare Worker melalui satu wildcard DNS record dan satu Worker Route. Hostname yang lebih dalam seperti web.demo.instara.app dapat di-resolve oleh wildcard DNS record yang sama, tetapi tetap gagal sebelum Worker dijalankan karena edge certificate tidak mencakup hostname tersebut.

Perbedaan ini penting karena ada tiga mekanisme independen yang terlibat dalam sebuah request:

DNS resolution
      |
      v
Worker Route matching
      |
      v
TLS certificate coverage

Ketiganya menggunakan sintaks wildcard, tetapi aturan pencocokannya tidak identik.

Wildcard DNS membawa hostname ke Cloudflare

Untuk setup Worker tanpa origin, proxied wildcard DNS record dapat menggunakan reserved IPv6 discard prefix sebagai placeholder:

Type:    AAAA
Name:    *
Content: 100::
Proxy:   Proxied

Bagian yang menentukan adalah proxy status. Cloudflare menerima request di edge-nya, bukan mengirim client langsung ke 100::. Placeholder tersebut tidak mengidentifikasi Worker dan bukan IP address milik Worker.

Wildcard DNS record untuk *.instara.app bersifat multi-level secara default. Selama tidak ada DNS record yang lebih spesifik, record tersebut dapat me-resolve keduanya:

demo.instara.app
web.demo.instara.app

Perilaku DNS ini lebih luas daripada cakupan sertifikat yang diberikan Universal SSL.

Untuk hostname tetap ketika Worker menjadi application origin, Cloudflare merekomendasikan Custom Domain karena DNS record dan sertifikat dibuat otomatis. Namun, Custom Domain membutuhkan exact hostname match dan tidak mendukung wildcard DNS record. Karena itu, subdomain dinamis memerlukan susunan routing yang berbeda.

Worker Route menentukan Worker yang dijalankan

DNS hanya membuat hostname dapat dijangkau melalui Cloudflare. Worker Route yang menghubungkan URL pattern dengan Worker.

Konfigurasi Wrangler untuk seluruh subhost tingkat pertama maupun yang lebih dalam di bawah instara.app dapat menggunakan:

{
  "name": "instara-worker",
  "main": "src/index.js",
  "compatibility_date": "2026-09-19",
  "workers_dev": false,
  "routes": [
    {
      "pattern": "*.instara.app/*",
      "zone_name": "instara.app"
    }
  ]
}

Route:

*.instara.app/*

cocok dengan subhost seperti:

demo.instara.app
alice.instara.app
web.demo.instara.app

tetapi tidak cocok dengan apex hostname:

instara.app

Jika apex harus menjalankan Worker yang sama, tambahkan route kedua alih-alih menggunakan *instara.app/*:

{
  "routes": [
    {
      "pattern": "instara.app/*",
      "zone_name": "instara.app"
    },
    {
      "pattern": "*.instara.app/*",
      "zone_name": "instara.app"
    }
  ]
}

Perbedaan ini disengaja. Route yang diawali *instara.app juga cocok dengan nama seperti myinstara.app, karena wildcard dapat menyerap karakter apa pun. Memisahkan route apex dan subhost mencegah pencocokan yang tidak diinginkan tersebut.

Jika beberapa route cocok, Cloudflare menggunakan pattern yang paling spesifik. Dengan begitu, sebagian besar subdomain dapat diarahkan ke satu Worker sementara hostname seperti api.instara.app dicadangkan untuk Worker lain.

Worker dapat mengambil identitas tenant dari hostname

Setelah request mencapai Worker, routing tenant dapat dilakukan di dalam kode. Worker minimal dapat memvalidasi suffix zone dan mengambil semua bagian sebelum .instara.app:

const ROOT_DOMAIN = "instara.app";

function getTenant(request) {
  const hostname = new URL(request.url).hostname.toLowerCase();
  const suffix = `.${ROOT_DOMAIN}`;

  if (!hostname.endsWith(suffix)) {
    return null;
  }

  const tenant = hostname.slice(0, -suffix.length);

  return tenant || null;
}

export default {
  async fetch(request) {
    const tenant = getTenant(request);

    if (!tenant) {
      return new Response("Tenant not found", {
        status: 404,
      });
    }

    return Response.json({
      tenant,
      hostname: new URL(request.url).hostname,
    });
  },
};

Request ke:

https://demo.instara.app/api

menghasilkan nilai tenant:

demo

Untuk:

https://web.demo.instara.app/api

fungsi yang sama menghasilkan:

web.demo

Ini dapat berguna jika seluruh prefix memang dijadikan tenant key. Jika arsitekturnya memperlakukan web sebagai nama aplikasi dan demo sebagai tenant, parser perlu schema hostname yang eksplisit, bukan sekadar mengambil seluruh prefix.

DNS dapat berhasil sementara TLS tetap gagal

Ini batas yang sering membingungkan.

Cloudflare Universal SSL mencakup zone apex dan satu tingkat subdomain:

instara.app          covered
demo.instara.app     covered
web.instara.app      covered

Secara default, cakupan tersebut tidak termasuk hostname yang lebih dalam:

web.demo.instara.app
api.demo.instara.app

Browser karena itu dapat me-resolve web.demo.instara.app melalui wildcard DNS record, terhubung ke Cloudflare, lalu gagal saat TLS handshake sebelum Worker dijalankan.

Chrome biasanya menampilkan:

ERR_SSL_VERSION_OR_CIPHER_MISMATCH

Kontradiksi yang tampak ini hilang ketika request dipisahkan berdasarkan tahapnya:

web.demo.instara.app
        |
        | wildcard DNS resolves
        v
Cloudflare edge
        |
        | certificate does not cover hostname
        X
Worker never receives the request

DNS lookup yang berhasil bukan bukti bahwa cakupan sertifikat HTTPS sudah benar.

Wildcard certificate hanya mencakup satu tingkat hostname

Sertifikat untuk:

*.instara.app

mencakup:

demo.instara.app
web.instara.app

tetapi tidak mencakup:

web.demo.instara.app

Untuk mencakup namespace yang lebih dalam itu, sertifikat perlu memasukkan hostname yang sesuai seperti:

*.demo.instara.app

Cloudflare Advanced Certificate Manager mendukung multi-level subdomain, tetapi setiap wildcard tetap hanya mencakup satu tingkat subdomain. Total TLS menjadi opsi lain: fitur tersebut dapat menerbitkan sertifikat individual secara otomatis untuk proxied hostname yang tidak tercakup Universal SSL.

Aturan sertifikat ini independen dari perilaku wildcard Cloudflare DNS. DNS *.instara.app dapat bersifat multi-level sementara TLS *.instara.app tetap hanya satu tingkat.

Gunakan namespace tenant satu tingkat jika memungkinkan

Untuk layanan multi-tenant, model hostname yang paling sederhana biasanya:

{tenant}.instara.app

Contoh:

demo.instara.app
acme.instara.app
customer-123.instara.app

Struktur ini menyelaraskan tiga properti yang berguna:

wildcard DNS    -> *.instara.app
Worker Route    -> *.instara.app/*
Universal SSL   -> *.instara.app

Tidak diperlukan DNS record per tenant, satu Worker dapat membaca hostname, dan Universal SSL mencakup first-level tenant hostname yang dihasilkan.

Struktur seperti:

{app}.{tenant}.instara.app

tetap valid, tetapi requirement sertifikat berubah. Jika web.demo.instara.app dan api.demo.instara.app menjadi bagian dari desain publik, provisioning sertifikat menjadi bagian dari proses onboarding tenant, bukan detail sampingan.

Perlakukan hostname sebagai tiga lapisan konfigurasi terpisah

Mental model yang tepat bukan “wildcard menunjuk ke Worker.” Pisahkan menjadi:

DNS:
Can this hostname resolve through Cloudflare?

Route:
If the request reaches Cloudflare, which Worker runs?

TLS:
Can Cloudflare present a certificate valid for this exact hostname?

Untuk *.instara.app, proxied wildcard DNS record dan wildcard Worker Route dapat membawa ruang hostname dinamis yang besar melalui satu Worker. Namespace TLS tetap membutuhkan desain tersendiri. Pemisahan ini membuat error seperti ERR_SSL_VERSION_OR_CIPHER_MISMATCH jauh lebih mudah didiagnosis dan mencegah wildcard DNS record yang berfungsi dianggap sebagai dukungan HTTPS yang sudah lengkap.