7 মিনিট

ডেভ, স্টেজিং, প্রোড-এর জন্য পরিবেশ কনফিগারেশন প্যাটার্ন

ওয়েব, ব্যাকএন্ড এবং মোবাইলে dev, staging, prod জুড়ে URL, কী এবং ফিচার ফ্ল্যাগ কোড থেকে সরিয়ে রেখে পরিবেশ কনফিগ প্যাটার্ন।

ডেভ, স্টেজিং, প্রোড-এর জন্য পরিবেশ কনফিগারেশন প্যাটার্ন

কেন হার্ডকোড করা কনফিগ সমস্যা করে দেয়

শুরুতে হার্ডকোড করা কনফিগ ঠিক আছে মনে হয়। তারপর আপনি একটি staging পরিবেশ, দ্বিতীয় একটি API বা দ্রুত কোনো ফিচার সুইচ প্রয়াস করেন, এবং সেই “সরল” পরিবর্তনটা রিলিজ ঝুঁকিতে পরিণত হয়। সমাধান সহজ: পরিবেশভিত্তিক মান সোর্স ফাইল থেকে রাখুন এবং একটি পূর্বনির্ধারিত সেটআপে নিয়ে আসুন।

সাধারণ সমস্যাগুলো সহজে চোখে পড়ে:

  • অ্যাপের মধ্যে বেক করা API base URL (টেস্ট করার সময় প্রোড কল করা, বা রিলিজের পরে dev কল হওয়া)
  • রেপোজিটরিতে কমিট করা API কী (লিক, অপ্রত্যাশিত বিল, জরুরি রোটেশন)
  • কনস্ট্যান্ট হিসেবে লেখা ফিচার টগল (কিছু বন্ধ করতে কোড শিপ করতে হবে)
  • অ্যানালিটিক্স ও এরর রিপোর্টিং ID হার্ডকোড (ডেটা ভুল জায়গায় যায়)

"শুধু প্রোডের জন্য বদলে দাও" মানসিকতা শেষ মুহূর্তের এডিটের অভ্যাস তৈরি করে। সেসব এডিট প্রায়ই রিভিউ, টেস্ট ও পুনরাবৃত্তির বাইরে চলে যায়। এক ব্যক্তি URL পরিবর্তন করে, আরেক ব্যক্তি কী বদলায়, এবং এখন আপনি একটি সহজ প্রশ্নের উত্তর দিতে পারেন না: এই বিল্ডের সাথে ঠিক কোন কনফিগ শিপ হয়েছে?

একটি সাধারণ দৃশ্যপট: আপনি একটি নতুন মোবাইল ভার্সন স্টেজিং এর বিরুদ্ধে তৈরি করেন, তারপর কেউ রিলিজের ঠিক আগে URL প্রোডে ঘোরান। পরের দিন ব্যাকএন্ড আবার পরিবর্তন করে, এবং আপনাকে রোলব্যাক করতে হয়। যদি URL হার্ডকোড করা থাকে, রোলব্যাক মানে আরেকটি অ্যাপ আপডেট। ব্যবহারকারীরা অপেক্ষা করে, এবং সাপোর্ট টিকিট বাড়ে।

এখানে লক্ষ্য একটি সহজ স্কিম: ওয়েব অ্যাপ, Go ব্যাকএন্ড, এবং Flutter মোবাইল অ্যাপে কাজ করে এমন নীতি:

  • কোড বনাম কনফিগে কী থাকা উচিৎ তা স্পষ্ট করা
  • dev, staging, এবং prod এর জন্য নিরাপদ ডিফল্ট
  • এমন ফিচার সুইচ যা সম্পূর্ণ রিবিল্ড ছাড়াই বদলানো যায়
  • গোপনীয়তা কোডবেসের বাইরে রাখা এবং রোটেট করার সুযোগ রাখা

dev, staging, এবং prod এর মধ্যে আসলেই কী বদলে যায়

Dev, staging, এবং prod একই অ্যাপ যে তিনটি ভিন্ন জায়গায় চলছে মনে করানো উচিত। উদ্দেশ্য হলো আচরণ নয়, মান বদলানো।

যা বদলানো উচিৎ: অ্যাপ কোথায় চলছে বা কে ব্যবহার করছে তার সাথে যুক্ত সবকিছু — base URL ও হোস্টনেম, ক্রিডেনশিয়াল, স্যান্ডবক্স বনাম রিয়েল ইন্টিগ্রেশন, এবং প্রোডে কড়া সিকিউরিটি সেটিংস বা লগ লেভেলের মতো সেফটি কন্ট্রোল।

যা অপরিবর্তিত থাকা উচিৎ: লজিক এবং অংশগুলোর মধ্যে কন্ট্রাক্ট। API রুট, অনুরোধ ও উত্তর কাঠামো, ফিচার নাম, এবং মূল ব্যবসায়িক নিয়মগুলো পরিবেশভেদে ভিন্ন হওয়া উচিত নয়। যদি staging ভিন্ন আচরণ করে, সেটি প্রোডের জন্য নির্ভরযোগ্য রিহার্সাল বন্ধ করে দেয়।

"নতুন পরিবেশ" বনাম "নতুন কনফিগ ভ্যালু" এর জন্য একটি বাস্তবসম্মত নিয়ম: একটি নতুন পরিবেশ তৈরি করুন শুধুমাত্র যখন আপনাকে আলাদা সিস্টেম দরকার (অলাদা ডাটা, অ্যাক্সেস, এবং ঝুঁকি)। যদি আপনি শুধুমাত্র আলাদা endpoint বা আলাদা সংখ্যা চান, একটি কনফিগ ভ্যালু যোগ করুন।

উদাহরণ: আপনি একটি নতুন সার্চ প্রোভাইডার পরীক্ষা করতে চান। যদি এটা ছোট একটি গ্রুপের জন্য চালু করা নিরাপদ হয়, একটি স্টেজিং রাখুন এবং ফিচার ফ্ল্যাগ যোগ করুন। যদি আলাদা ডাটাবেস এবং কঠোর অ্যাক্সেস কন্ট্রোল লাগে, তখন নতুন পরিবেশ যুক্ত করা যুক্তিযুক্ত।

একটি ব্যবহারযোগ্য কনফিগ মডেল যা সব জায়গায় পুনরায় ব্যবহার করা যাবে

ভালো সেটআপ একটাই করে: দুর্ঘটনাবশত dev URL, টেস্ট কী, বা অসম্পূর্ণ ফিচার শিপ হওয়া কঠিন করে দেয়।

প্রতি অ্যাপে (web, backend, mobile) একই তিনটি স্তর ব্যবহার করুন:

  1. Defaults: সাধারণ জায়গায় কাজ করার নিরাপদ মান।
  2. Environment overrides: dev, staging, prod এর জন্য যা বদলে যায়।
  3. Secrets: সংবেদনশীল মান যা রেপোতে কখনো থাকে না।

ভ্রান্তি এড়াতে, প্রতি অ্যাপের জন্য একটি সিংগল সোর্স অব ট্রুথ বেছে নিন এবং তাতে অন্বিষ্ট থাকুন। উদাহরণস্বরূপ, ব্যাকএন্ড স্টার্টআপে environment variables পড়ে, ওয়েব অ্যাপ বিল্ড-টাইম ভ্যারিয়েবল বা ছোট runtime config ফাইল পড়ে, এবং মোবাইল অ্যাপ বিল্ড টাইমে একটি ছোট environment ফাইল পড়ে। প্রতিটি অ্যাপের অভ্যন্তরে সঙ্গতি বজায় রাখা একে অপরের থেকে একই মেকানিজম জোর করার চেয়ে বেশি গুরুত্বপূর্ণ।

একটি সরল, পুনরায় ব্যবহারযোগ্য স্কিম দেখতে কেমন:

  • Defaults কোডে অ-সংবেদনশীল কনস্ট্যান্ট হিসেবে থাকে (timeouts, page size, retry counts)।
  • Overrides env-নির্দিষ্ট ফাইল বা environment variables এ থাকে (API base URL, analytics on/off)।
  • Secrets একটি সিক্রেট স্টোরে থাকে এবং deploy/build সময় ইনজেক্ট করা হয় (JWT secret, database password, third-party API keys)।

বোঝার মতো নামকরণ

প্রতিটি কনফিগ আইটেম এমন নাম দিন যা তিনটি প্রশ্নের উত্তর দেয়: এটি কী, কোথায় প্রযোজ্য, এবং টাইপ কী।

একটি ব্যবহারযোগ্য কনভেনশন:

  • অ্যাপ দ্বারা প্রিফিক্স: WEB_, API_, MOBILE_
  • ALL_CAPS ও আন্ডারস্কোর ব্যবহার
  • উদ্দেশ্য দ্বারা গ্রুপ: API_BASE_URL, AUTH_JWT_SECRET, FEATURES_NEW_CHECKOUT
  • বুলিয়ান স্পষ্ট রাখুন: FEATURES_SEARCH_ENABLED=true

এভাবে, কেউ ধরে নিতে হবে না যে “BASE_URL” React অ্যাপের জন্য, Go সার্ভিসের জন্য, না Flutter অ্যাপের জন্য।

ধাপে ধাপে: ওয়েব অ্যাপ কনফিগ (React) হার্ডকোড ছাড়া

React কোড ব্রাউজারে চলে, তাই আপনি যা শিপ করেন সবই পড়া যায়। লক্ষ্য সহজ: সিক্রেট সার্ভারে রাখুন, এবং ব্রাউজার শুধুমাত্র "সেফ" সেটিংস পড়ুক যেমন API base URL, অ্যাপ নাম, বা সংবেদনশীল নয় এমন ফিচার টগল।

1) ঠিক করুন কী build-time আর কী runtime

Build-time কনফিগ তখন ইনজেক্ট হয় যখন আপনি ব্যাণ্ডেল বানান। যা বিরলে বদলায় এবং প্রকাশ করতে নিরাপদ সেগুলোর জন্য ঠিক আছে।

Runtime কনফিগ অ্যাপ শুরুতে লোড করা হয় (উদাহরণ: অ্যাপের সাথে সার্ভ করা ছোট JSON ফাইল থেকে বা ইনজেক্ট করা গ্লোবাল থেকে)। ডিপ্লয়ের পরে আপনি যা বদলাতে চাইবেন এমন মানের জন্য এটা ভালো, যেমন পরিবেশগুলোর মধ্যে API base URL সোয়াপ করা।

সরল নিয়ম: যদি বদলানোতে UI রিবিল্ড উচিত না হয়, তাহলে সেটি runtime করুন।

2) API base URL কমিট না করে স্টোর করুন

ডেভেলপারদের জন্য লোকাল ফাইল রাখুন (কমিট না করা) এবং বাস্তব মান CI/CD পাইপলাইনে সেট করুন।

  • Local dev: .env.local (gitignored) ব্যবহার করুন, উদাহরণ VITE_API_BASE_URL=http://localhost:8080
  • CI/CD: বিল্ড জব-এ VITE_API_BASE_URL environment variable হিসেবে সেট করুন, অথবা deploy সময় একটি runtime config ফাইলে রাখুন

Runtime উদাহরণ (অ্যাপের পাশে সার্ভ করা):

{ "apiBaseUrl": "https://api.staging.example.com", "features": { "newCheckout": false } }

তারপর একবার startup-এ এটি লোড করুন এবং এক জায়গায় রাখুন:

export async function loadConfig() {
  const res = await fetch('/config.json', { cache: 'no-store' });
  return res.json();
}

3) ব্রাউজারে শুধুমাত্র নিরাপদ মান এক্সপোজ করুন

React env vars-কে सार्वजनिक হিসেবে বিবেচনা করুন। পাসওয়ার্ড, প্রাইভেট API কী, বা ডাটাবেস URL ওয়েব অ্যাপে রাখবেন না।

নিরাপদ উদাহরণ: API base URL, Sentry DSN (public), build version, এবং সাধারণ ফিচার ফ্ল্যাগ।

ধাপে ধাপে: ব্যাকএন্ড কনফিগ (Go) যা আপনি ভ্যালিডেট করতে পারেন

ব্যাকএন্ড কনফিগ নিরাপদ থাকে যখন তা টাইপ করা থাকে, environment variables থেকে লোড হয়, এবং সার্ভার ট্র্যাফিক গ্রহণ শুরুর আগে ভ্যালিডেট করা হয়।

শুরুতে নির্ধারণ করুন ব্যাকএন্ড চালাতে কি কি লাগে, এবং সেগুলো স্পষ্ট করুন। সাধারণ "অবশ্যই থাকা" মানগুলো হচ্ছে:

  • APP_ENV (dev, staging, prod)
  • HTTP_ADDR (উদাহরণ :8080)
  • DATABASE_URL (Postgres DSN)
  • PUBLIC_BASE_URL (callback ও লিঙ্কের জন্য)
  • API_KEY (তৃতীয় পক্ষ সেবার জন্য)

তারপর সেগুলো একটি struct-এ লোড করে সার্ভার শুরুর আগে মিসিং বা ভুল হলে ফেইল করুন। এভাবে আপনি সেকেন্ডের মধ্যে সমস্যা খুঁজে পাবেন, পার্শ্ববর্তী deploy-এ নয়।

package config

import (
	"errors"
	"net/url"
	"os"
	"strings"
)

type Config struct {
	Env           string
	HTTPAddr      string
	DatabaseURL   string
	PublicBaseURL string
	APIKey        string
}

func Load() (Config, error) {
	c := Config{
		Env:           mustGet("APP_ENV"),
		HTTPAddr:      getDefault("HTTP_ADDR", ":8080"),
		DatabaseURL:   mustGet("DATABASE_URL"),
		PublicBaseURL: mustGet("PUBLIC_BASE_URL"),
		APIKey:        mustGet("API_KEY"),
	}
	return c, c.Validate()
}

func (c Config) Validate() error {
	if c.Env != "dev" && c.Env != "staging" && c.Env != "prod" {
		return errors.New("APP_ENV must be dev, staging, or prod")
	}
	if _, err := url.ParseRequestURI(c.PublicBaseURL); err != nil {
		return errors.New("PUBLIC_BASE_URL must be a valid URL")
	}
	if !strings.HasPrefix(c.DatabaseURL, "postgres://") {
		return errors.New("DATABASE_URL must start with postgres://")
	}
	return nil
}

func mustGet(k string) string {
	v, ok := os.LookupEnv(k)
	if !ok || strings.TrimSpace(v) == "" {
		panic("missing env var: " + k)
	}
	return v
}

func getDefault(k, def string) string {
	if v, ok := os.LookupEnv(k); ok && strings.TrimSpace(v) != "" {
		return v
	}
	return def
}

এটি ডাটাবেস DSN, API কী, এবং callback URL কোড ও git-এ থাকা থেকে বিরত রাখে। হোস্টেড সেটআপে, আপনি environment ভ্যারিয়েবল প্রতিটি পরিবেশে ইনজেক্ট করেন যাতে dev, staging, এবং prod আলাদা মান নিয়ে কাজ করে এক লাইনে কোনো পরিবর্তন ছাড়াই।

ধাপে ধাপে: মোবাইল কনফিগ (Flutter) যা নমনীয় থাকে

Rollback config mistakes fast
Test config changes confidently and roll back fast when something looks off.

Flutter অ্যাপ সাধারণত দুই স্তরের কনফিগ দরকার: build-time flavors (কি আপনি শিপ করছেন) এবং runtime সেটিংস (অ্যাপ রিলিজ ছাড়া বদলাতে পারে)। এসব আলাদা রাখলে “শুধু এক URL পরিবর্তন” জরুরি রিবিল্ডে পরিণত হয় না।

1) ফ্লেভার্সকে আইডেন্টিটি জন্য ব্যবহার করুন, না कि endpoints-এর জন্য

তিনটি flavor তৈরি করুন: dev, staging, prod। Flavors এমন জিনিস নিয়ন্ত্রণ করবে যা বিল্ড টাইমে স্থির থাকা উচিত, যেমন অ্যাপ নাম, bundle id, signing, analytics প্রজেক্ট, এবং debug টুলস চালু আছে কিনা।

তারপর কেবল non-sensitive ডিফল্ট --dart-define (বা CI) দিয়ে পাস করুন যাতে এগুলো কোডে হার্ডকোড না হয়:

  • ENV=staging
  • DEFAULT_API_BASE=https://api-staging.example.com
  • CONFIG_URL=https://config.example.com/mobile.json

Dart-এ এগুলো String.fromEnvironment দিয়ে পড়ুন এবং স্টার্টআপে একটি সহজ AppConfig অবজেক্ট তৈরি করুন।

2) URL এবং সুইচগুলো fetched config-এ রাখুন

ছোট endpoint পরিবর্তনের জন্য রিবিল্ড এড়াতে, API base URL-কে কনস্ট্যান্ট হিসেবে না ধরুন। অ্যাপ লঞ্চে একটি ছোট কনফিগ ফাইল ফেচ করুন (এবং ক্যাশ করুন)। Flavor কেবল কোথা থেকে কনফিগ ফETCH করতে হবে সেটা সেট করবে।

একটি বাস্তবসম্মত বিভাজন:

  • Flavor (build-time): অ্যাপ আইডেন্টিটি, ডিফল্ট config URL, crash reporting project
  • Remote config (runtime): API base URL, ফিচার ফ্ল্যাগ, রোলআউট শতাংশ, মেইনটেন্যান্স মোড
  • Secrets: অ্যাপে কখনো শিপ করবেন না (মোবাইল বাইনারি ইনস্পেক্ট করা যায়)

যদি আপনার ব্যাকএন্ড সরান, আপনি remote config আপডেট করে নতুন base URL পয়েন্ট করবেন। বিদ্যমান ব্যবহারকারীরা পরবর্তী লঞ্চে এটি পাবে, এবং শেষ ক্যাশ করা মানকে নিরাপদ ফallback হিসেবে রাখুন।

ফিচার ফ্ল্যাগ এবং সুইচ যা বিশৃঙ্খলা সৃষ্টি করে না

ফিচার ফ্ল্যাগ ধীরে ধীরে রোলআউট, A-B টেস্ট, দ্রুত কিল-সুইচ, এবং স্টেজিংয়ে ঝুঁকিপূর্ণ পরিবর্তন টেস্ট করার জন্য দরকারী। এগুলো নিরাপত্তার বিকল্প নয়। যদি কোনো ফ্ল্যাগ এমন কিছু রক্ষা করে যা নিরাপদ থাকতে হবে, সেটি ফ্ল্যাগ না হয়ে auth নিয়ম।

প্রতিটি ফ্ল্যাগকে একটি API-র মতো behandeln করুন: স্পষ্ট নাম, একজন মালিক, এবং একটি শেষ তারিখ।

ইচ্ছা প্রকাশ করা নামকরণ

নাম এমন হওয়া উচিত যা বলে দেয় ফ্ল্যাগ ON হলে কী হয়, এবং প্রোডাক্টের কোন অংশকে স্পর্শ করে। সহজ স্কিম:

  • feature.checkout_new_ui_enabled (কাস্টমার-ফেসিং ফিচার)
  • ops.payments_kill_switch (জরুরি বন্ধ সুইচ)
  • exp.search_rerank_v2 (একটি পরীক্ষা)
  • release.api_v3_rollout_pct (ধীর রোলআউট)
  • debug.show_network_logs (ডায়াগনস্টিক)

পজিটিভ বুলিয়ান (..._enabled) পছন্দ করুন। একটি স্থিতিশীল প্রিফিক্স রাখুন যাতে সার্চ ও অডিট সহজ হয়।

ডিফল্ট, গার্ডরেইল, ও ক্লিনআপ

নিরাপদ ডিফল্ট দিয়ে শুরু করুন: যদি ফ্ল্যাগ সার্ভিস ডাউন থাকে, আপনার অ্যাপ স্থিতিশীল ভার্সন মতো আচরণ করা উচিত।

বাস্তবসম্মত প্যাটার্ন: ব্যাকএন্ডে নতুন endpoint শিপ করুন, পুরনোটি চালু রাখুন, এবং release.api_v3_rollout_pct দিয়ে ধীরে ধীরে ট্রাফিক সরান। যদি এরর বাড়ে, ফ্ল্যাগ ফিরিয়ে দিন হটফিক্স ছাড়াই।

ফ্ল্যাগ জমে না যাওয়ার জন্য কয়েকটি নিয়ম:

  • প্রতিটি ফ্ল্যাগের একজন মালিক এবং একটি “remove by” তারিখ থাকবে
  • পূর্ণ রোলআউটের 1-2 রিলিজের মধ্যে ফ্ল্যাগ সরান
  • ডিবাগিংয়ের জন্য কী ফ্লোতে ফ্ল্যাগ মান লগ করুন
  • মাসিকভাবে ফ্ল্যাগ রিভিউ করুন যেমন আপনি dependency রিভিউ করেন

সিক্রেটস: স্টোরেজ, অ্যাক্সেস, এবং রোটেশনের মৌলিক কথা

Build with environment-ready config
Create a React, Go, or Flutter app and set dev, staging, and prod values from day one.

"সিক্রেট" হলো এমন কিছু যা লিক হলে ক্ষতি করবে। ভাবুন API টোকেন, ডাটাবেস পাসওয়ার্ড, OAuth ক্লায়েন্ট সিক্রেট, সাইনিং কী (JWT), webhook সিক্রেট, এবং প্রাইভেট সার্টিফিকেট। সিক্রেট নয়: API base URL, build নম্বর, ফিচার ফ্ল্যাগ, বা পাবলিক অ্যানালিটিক্স ID।

সিক্রেটসকে বাকী সেটিংস থেকে আলাদা রাখুন। ডেভেলপাররা নিরাপদ কনফিগ স্বাধীনভাবে বদলাতে পারবে, আর সিক্রেটগুলো কেবল runtime-এ প্রয়োজন অনুযায়ী ইনজেক্ট হবে।

পরিবেশ অনুযায়ী সিক্রেট কোথায় থাকা উচিৎ

Dev-এ সিক্রেট লোকাল ও ডিস্পোজেবল রাখুন। .env ফাইল বা OS keychain ব্যবহার করুন এবং রিসেট করা সহজ রাখুন। কখনো কমিট করবেন না।

Staging ও Prod-এ সিক্রেট ডেডিকেটেড সিক্রেট স্টোরে থাকা উচিৎ, না আপনার কোড রেপোতে, না চ্যাট লগে, না মোবাইল অ্যাপে বেক করা।

  • Web (React): ব্রাউজারে সিক্রেট রাখবেন না। ক্লায়েন্ট যদি টোকেন চায়, ব্যাকএন্ড থেকে শর্ট-লিভ টোকেন ইস্যু করুন।
  • Backend (Go): সিক্রেট environment variables বা সিক্রেট ম্যানেজার থেকে স্টার্টআপে লোড করুন এবং মেমরিতেই রাখুন।
  • Mobile (Flutter): অ্যাপটিকে পাবলিক হিসেবে বিবেচনা করুন। অ্যাপে থাকা যেকোনো "সিক্রেট" বের করা যায়, তাই ব্যাকএন্ড-ইস্যু করা টোকেন ও ডিভাইসsecure storage কেবল ইউজার সেশন ডেটার জন্য ব্যবহার করুন।

রোটেশন মৌলিক (প্রোড ব্রেক না করে)

রোটেশন তখন ব্যর্থ হয় যখন আপনি একটি কী বদলান এবং ভুলে যান পুরনো ক্লায়েন্টগুলো এখনও সেটাই ব্যবহার করছে। ওভারল্যাপ উইন্ডো পরিকল্পনা করুন।

  • একই সময়ে দুইটি বৈধ সিক্রেট সমর্থন করুন (active + previous) ছোট উইন্ডোর জন্য
  • প্রথমে নতুন সিক্রেট রোল আউট করুন, তারপর "active" পয়েন্টার পরিবর্তন করুন
  • অথরাইজেশন ফেইলগুলা মনিটর করুন, তারপর উইন্ডো শেষ হলে পুরনো সিক্রেট সরান
  • নিরাপদ ডিবাগিংয়ের জন্য সিক্রেট ভার্সনগুলো লগ করুন (সিক্রেট মান নয়)

API কী, webhook সিক্রেট, এবং সাইনিং কীগুলোর জন্য এই ওভারল্যাপ পদ্ধতি কাজ করে এবং অপ্রত্যাশিত আউটেজ এড়ায়।

উদাহরণ রোলআউট: API URL বদলানো ব্যবহারকারীদের না ভাঙিয়ে

আপনার কাছে একটি স্টেজিং API এবং একটি নতুন প্রোড API আছে। লক্ষ্য হলো ধাপে ধাপে ট্রাফিক সরানো, এবং কোন সমস্যা হলে দ্রুত ফিরিয়ে আনা। অ্যাপ যদি config থেকে API base URL পড়ে, কোডে না থাকে, এটি সহজ।

প্রতিটি জায়গায় API URL-কে deploy-time ভ্যালু হিসেবে বিবেচনা করুন। ওয়েব অ্যাপে (React) এটি প্রায়ই build-time মান বা runtime config ফাইল। মোবাইলে (Flutter) এটি সাধারণত flavor প্লাস remote config। ব্যাকএন্ডে (Go) এটি runtime env var। গুরুত্বপূর্ণ অংশ হলো সঙ্গতি: কোড একটি ভ্যারিয়েবল নাম (উদাহরণ API_BASE_URL) ব্যবহার করে এবং কৌম্পোনেন্ট, সার্ভিস, বা স্ক্রিনে URL এমবেড করে না।

একটি নিরাপদ ধাপে ধাপে রোলআউট দেখতে পারে:

  • প্রোড API ডিপ্লয় করুন এবং এটিকে "ডার্ক" রাখুন (শুধু অভ্যন্তরীণ ট্রাফিক) যখন স্টেজিং ডিফল্ট থাকে।
  • প্রথমে ব্যাকএন্ড নির্ভরশীলতাগুলো সোয়াপ করুন (যদি আপনার ব্যাকএন্ড অন্য সার্ভিস কল করে), env vars ব্যবহার করে এবং দ্রুত রিস্টার্ট করে।
  • ওয়েব ট্রাফিক ধীরে ধীরে সরান (বা কেবল অভ্যন্তরীণ অ্যাকাউন্টে)।
  • নতুন সেটআপ নিয়ে মোবাইল অ্যাপ রিলিজ করুন, কিন্তু সার্ভার-কন্ট্রোলড ফ্ল্যাগ রাখুন যাতে সুইচ করা বিলম্বিত করা যায়।
  • ট্রাফিক ধীরে বাড়ান এবং রোলব্যাক প্রস্তুত রাখুন।

ভেরিফিকেশন মূলত মিসম্যাচ দ্রুত ধরার উপর। বাস্তব ব্যবহারকারীরা পরিবর্তনের আগে নিশ্চিত করুন হেলথ এন্ডপয়েন্ট সাড়া দেয়, অথ ফ্লো কাজ করে, এবং একই টেস্ট অ্যাকাউন্ট একটি মূল জার্নি এক্সিকিউট করতে পারে।

শিপ করার আগে দ্রুত চেকলিস্ট

বেশিরভাগ প্রোডাকশনের কনফিগ বাগ সাধারণ: স্টেজিং মান মিস, একটি ফ্ল্যাগ ডিফল্ট উল্টে যাওয়া, বা একটি API কী এক অঞ্চলে মিসিং। একটি দ্রুত পাস বেশিরভাগ ধরে।

ডিপ্লয় করার আগে তিনটি জিনিস নিশ্চিত করুন যে টার্গেট পরিবেশের সাথে মেলে: endpoints, secrets, এবং defaults।

  • Base URLs ঠিক জায়গায় পয়েন্ট করছে (API, auth, CDN, payments)। ওয়েব, ব্যাকএন্ড, এবং মোবাইল আলাদা করে চেক করুন।
  • প্রোডে টেস্ট কী নেই, এবং dev বা staging-এ প্রোড কীগুলো নেই। কী নামগুলো অ্যাপ কী আশা করে সেটাও ম্যাচ করে কিনা নিশ্চিত করুন।
  • ফিচার ফ্ল্যাগগুলো নিরাপদ ডিফল্টে আছে। যে কোনো ঝুঁকিপূর্ণ জিনিস ডিফল্টে বন্ধ থাকা উচিত এবং উদ্দেশ্যমতো চালু করা উচিত।
  • Build ও release সেটিংস মিলছে (bundle ID/package name, কাস্টম ডোমেইন, CORS origins, OAuth redirect URLs)।
  • ওবজারভেবিলিটি কনফিগার করা আছে (লগ, এরর রিপোর্টিং, ট্রেসিং) এবং সঠিক environment লেবেলে সেট আছে।

তারপর একটি দ্রুত স্মোক টেস্ট করুন। একটি বাস্তব ইউজার ফ্লো নিন এবং end-to-end চালান, নতুন ইনস্টল বা ক্লিন ব্রাউজার প্রোফাইল ব্যবহার করে যাতে ক্যাশড টোকেন ভরসা না করতে হয়।

  • অ্যাপ খুলুন এবং কনসোল এরর ছাড়াই লোড হচ্ছে কি না দেখুন।
  • সাইন ইন করুন এবং একটি API কল মেরুন যা অথ চায় (প্রোফাইল, সেটিংস, বা একটি সাধারণ ডাটা লিস্ট)।
  • একটি নিয়ন্ত্রণকৃত ফেলিওর ট্রিগার করুন (খারাপ ইনপুট বা অফলাইন মোড) এবং নিশ্চিত করুন ব্যবহারকারী একটি বন্ধুত্বপূর্ণ বার্তা দেখে, খালি স্ক্রিন নয়।
  • লগ ও এরর রিপোর্টিং চেক করুন: একটি টেস্ট এরর কয় মিনিটের মধ্যে সঠিক পরিবেশের অধীনে দেখা উচিত।

বাস্তবিক অভ্যাস: staging-কে প্রোডের মতো আচরণ করুন কিন্তু বিভিন্ন মান নিয়ে। মানে একই কনফিগ স্কিমা, একই ভ্যালিডেশন রুল, এবং একই ডিপ্লয়মেন্ট আকৃতি। কেবল মানগুলোই আলাদা হওয়া উচিত, কাঠামো নয়।

আউটেজের দিকে নিয়ে যায় এমন সাধারণ ভুল

Write the config plan
Map your config contract first, then generate the app around it in planning mode.

অধিকাংশ কনফিগ আউটেজ জটিল নয়। সেগুলো সাধারণ ভুল যা ফাইল, বিল্ড স্টেপ, এবং ড্যাশবোর্ড জুড়ে ছড়িয়ে থাকে, এবং কেউ উত্তর দিতে পারে না: "এই মুহূর্তে অ্যাপ কোন মানগুলো ব্যবহার করবে?" একটি ভালো সেটআপ এই প্রশ্নকে সহজ করে।

build-time এবং runtime সেটিংস মিশানো

একটি সাধারণ ফাঁদ হলো runtime মানগুলো build-time জায়গায় রাখা। React build-এ API base URL বেক করা হলে আপনাকে প্রতিটি পরিবেশের জন্য রিবিল্ড করতে হবে। তারপর কেউ ভুল artifact ডিপ্লয় করে এবং প্রোড স্টেজিংকে পয়েন্ট করে।

নিরাপদ নিয়ম: কেবল সেই মানগুলো বেক করুন যা রিলিজের পরে সত্যিই বদলাবে না (যেমন অ্যাপ ভার্সন)। পরিবেশ সংক্রান্ত বিস্তারিত (API URLs, ফিচার সুইচ, অ্যানালিটিক্স এন্ডপয়েন্ট) সম্ভব হলে runtime রাখুন, এবং সোর্স অব ট্রুথ স্পষ্ট করুন।

dev endpoints বা test কীগুলো শিপ করা

ডিফল্ট যদি "সাহায্যকারী" কিন্তু অনিরাপদ হয় তাহলে এই সমস্যা ঘটে। একটি মোবাইল অ্যাপ যদি কনফিগ পড়তে না পারে তাহলে dev API-তে ডিফল্ট হতে পারে, বা ব্যাকএন্ড যদি env var মিসিং হলে লোকাল ডাটাবেসে fallback করতে পারে। এটাই একটি ছোট কনফিগ ভুলকে পুরো আউটেজে পরিণত করে।

দুইটি অভ্যাস সাহায্য করে:

  • Fail closed: যদি একটি প্রয়োজনীয় মান মিসিং থাকে, স্পষ্ট এরর নিয়ে দ্রুত ক্র্যাশ করুন।
  • প্রোডকে ভুল কনফিগার করা কঠিন করুন: কোনো dev ডিফল্ট না রাখুন, কোনো টেস্ট কী প্রোডে গ্রহণ করবেন না, কোনো ডিবাগ এন্ডপয়েন্ট সক্রিয় থাকবে না।

বাস্তব উদাহরণ: শুক্রবার রাতে একটি রিলিজে প্রোড বিল্ডে স্টেজিং পেমেন্ট কী থাকে। সবকিছু “চলছিল” যতক্ষণ না চার্জ ব্যর্থ হতে শুরু করে। সমাধান নতুন পেমেন্ট লাইব্রেরি নয় — ভ্যালিডেশন যা প্রোডে নন-প্রোড কীগুলো প্রত্যাখ্যান করে।

staging-কে প্রোড থেকে বিচ্ছিন্ন করে ফেলা

যদি staging প্রোডের মতো না থাকে তাহলে ভুল কনফিডেন্স দেয়। ভিন্ন ডাটাবেস সেটিংস, মিসিং ব্যাকগ্রাউন্ড জব, বা অতিরিক্ত ফিচার ফ্ল্যাগ বাগগুলোকে কেবল রিলিজের পরে আসবে।

staging-কে প্রোডের কাছাকাছি রাখুন: একই কনফিগ স্কিমা, একই ভ্যালিডেশন রুল, এবং একই ডিপ্লয়মেন্ট আকৃতি প্রতিফলিত করুন। কেবল ভ্যালুগুলোই আলাদা হওয়া উচিত।

পরবর্তী ধাপ: কনফিগকে বিরক্তিকর, পুনরাবৃত্তিমূলক, এবং নিরাপদ করুন

লক্ষ্য ফ্যান্সি টুলিং নয়। লক্ষ্য হল বিরক্তিকর সঙ্গতি: একই নাম, একই টাইপ, একই নিয়ম dev, staging, এবং prod জুড়ে। যখন কনফিগ পূর্বানুমেয় হয়, রিলিজ ঝুঁকি কমে।

প্রথমে এক জায়গায় একটি স্পষ্ট কনফিগ কনট্রাক্ট লিখে রাখুন। সংক্ষিপ্ত কিন্তু নির্দিষ্ট রাখুন: প্রতিটি কী নাম, এর টাইপ (string, number, boolean), কোথা থেকে.allowed (env var, remote config, build-time), এবং ডিফল্ট। ক্লায়েন্ট অ্যাপে কখনো সেট করা যাবে না এমন মানগুলোর নোট যোগ করুন (যেমন প্রাইভেট API কীগুলো)। এই কনট্রাক্টকে একটি API হিসেবে বিবেচনা করুন: পরিবর্তন হলে রিভিউ লাগবে।

তারপর ভুলগুলো দ্রুত ব্যর্থ করতে করুন।Missing API base URL CI-তেই খুঁজে পাওয়া সবচেয়ে ভালো, না ডিপ্লয় পর। এমন automated validation যোগ করুন যা আপনার অ্যাপ যেমন কনফিগ লোড করে ঠিক সেইভাবে লোড করে এবং চেক করে:

  • প্রয়োজনীয় মানগুলো উপস্থিত (খালি স্ট্রিং নয়)
  • টাইপ সঠিক ("true" vs true বাগ নেই)
  • প্রোড-নির্দিষ্ট নিয়ম পাস করে (উদাহরণ: HTTPS বাধ্যতামূলক)
  • ফিচার ফ্ল্যাগ নামগুলো পরিচিত (টাইপো নেই)
  • সিক্রেটস রিপোতে কমিট হয়নি

সবশেষে, কনফিগ পরিবর্তন ভুল হলে সহজে পুনরুদ্ধার করা যায় এমন ব্যবস্থা রাখুন। যা চলছে তার স্ন্যাপশট নিন, একবারে একটাই পরিবর্তন করুন, দ্রুত যাচাই করুন, এবং রোলব্যাক পথ রাখুন।

যদি আপনি Koder.ai (koder.ai) মত কোন প্ল্যাটফর্ম দিয়ে বিল্ড ও ডিপ্লয় করেন, একই নিয়ম প্রযোজ্য: environment মানকে build ও hosting-এ ইনপুট হিসেবে বিবেচনা করুন, সিক্রেটস exported source-এ রাখবেন না, এবং শিপ করার আগে কনফিগ ভ্যালিডেট করুন। ঐ সঙ্গতি পুনরায় ডিপ্লয় ও রোলব্যাককে রুটিন করে তোলে।

যখন কনফিগ ডকুমেন্টেড, ভ্যালিডেটেড, এবং রিভার্সিবল হয়, তখন এটি আউটেজের উৎস না হয়ে শিপিংয়ের সাধারণ অংশে পরিণত হয়।

সাধারণ প্রশ্ন

কোডের বদলে কনফিগে কী রাখা উচিত?

পরিবেশভেদে বদলে যায় এমন মান সোর্স ফাইলের বাইরে রাখুন। সংবেদনশীল নয় এমন ডিফল্ট মান কোডে রাখুন, URL ও টগলের জন্য পরিবেশভিত্তিক সেটিংস ব্যবহার করুন এবং বিল্ড বা ডিপ্লয়ের সময় সিক্রেট ইনজেক্ট করুন।

কখন আমার নতুন পরিবেশ দরকার?

আলাদা ডেভ, স্টেজিং ও প্রোড পরিবেশ ব্যবহার করুন যখন আলাদা ডেটা, অ্যাক্সেস বা ঝুঁকি নিয়ন্ত্রণ দরকার। শুধু URL, সীমা বা সুইচ বদলালে তার বদলে একটি কনফিগ মান যোগ করুন।

আমি কি React অ্যাপে সিক্রেট সংরক্ষণ করতে পারি?

না। ব্রাউজারে পাঠানো সবকিছু ব্যবহারকারীরা দেখতে পারেন। প্রাইভেট কী ও পাসওয়ার্ড ব্যাকএন্ডে রাখুন, আর শুধু নিরাপদ মান প্রকাশ করুন, যেমন পাবলিক API URL বা একটি সাধারণ ফিচার ফ্ল্যাগ।

আমার ওয়েব অ্যাপে কি বিল্ড-টাইম নাকি রানটাইম কনফিগ ব্যবহার করা উচিত?

যে সেটিংস খুব কম বদলায় এবং প্রকাশ করা নিরাপদ, সেগুলোর জন্য বিল্ড-টাইম মান ব্যবহার করুন। ডিপ্লয়ের পরে যেসব মান বদলাতে হতে পারে, যেমন API বেস URL বা মেইনটেন্যান্স সুইচ, সেগুলোর জন্য রানটাইম কনফিগ লোড করুন।

একটি Go ব্যাকএন্ড কীভাবে কনফিগারেশন সামলাবে?

সার্ভিস চালুর সময় প্রয়োজনীয় এনভায়রনমেন্ট ভেরিয়েবলগুলো একটি টাইপড কনফিগ স্ট্রাক্টে লোড করুন। অনুমোদিত পরিবেশ, URL ও ডেটাবেস কানেকশন স্ট্রিং যাচাই করুন, তারপর প্রয়োজনীয় কোনো মান না থাকলে স্পষ্ট ত্রুটি দেখিয়ে স্টার্টআপ থামিয়ে দিন।

Flutter-এ ডেভ, স্টেজিং ও প্রোড কীভাবে সামলানো উচিত?

অ্যাপ আইডি, সাইনিং ও অ্যানালিটিক্স প্রজেক্টের মতো বিল্ড-নির্দিষ্ট তথ্যের জন্য Flutter flavors ব্যবহার করুন। API URL ও ফিচার ফ্ল্যাগের মতো সংবেদনশীল নয় এমন রানটাইম সেটিংস রিমোট কনফিগ উৎস থেকে আনুন।

ফিচার ফ্ল্যাগ জমতে না দেওয়ার উপায় কী?

ফ্ল্যাগ যে আচরণ চালু করে তার নামে ফ্ল্যাগের নাম দিন, যেমন feature.checkout_new_ui_enabled। প্রতিটি ফ্ল্যাগের একজন মালিক ও অপসারণের তারিখ নির্ধারণ করুন, ঝুঁকিপূর্ণ পরিবর্তন ডিফল্টভাবে বন্ধ রাখুন এবং পুরো রোলআউটের অল্প সময়ের মধ্যেই ফ্ল্যাগটি সরিয়ে দিন।

API কী ও ডেটাবেস পাসওয়ার্ড কোথায় সংরক্ষণ করা উচিত?

স্টেজিং ও প্রোডাকশন সিক্রেট নির্দিষ্ট সিক্রেট স্টোরে রাখুন, তারপর শুধু যেসব সার্ভিসের দরকার সেগুলোতেই ইনজেক্ট করুন। লোকাল ডেভেলপমেন্টের সিক্রেট উপেক্ষা করা লোকাল ফাইল বা OS কীচেইনে রাখুন।

ডাউনটাইম ছাড়া সিক্রেট রোটেট করব কীভাবে?

অল্প সময়ের ওভারল্যাপ পর্যায়ে পুরোনো ও নতুন ক্রেডেনশিয়াল একসঙ্গে চালান। নতুন মান দিয়ে ক্লায়েন্ট বা সার্ভিস ডিপ্লয় করুন, সক্রিয় ট্র্যাফিক বদলান, প্রমাণীকরণ ব্যর্থতা পর্যবেক্ষণ করুন, তারপর পুরোনো ক্রেডেনশিয়াল সরিয়ে দিন।

প্রোডাকশন রিলিজের আগে কী পরীক্ষা করা উচিত?

প্রতিটি এন্ডপয়েন্ট লক্ষ্য পরিবেশে নির্দেশ করছে কি না, প্রয়োজনীয় সিক্রেট আছে কি না এবং ঝুঁকিপূর্ণ ফ্ল্যাগগুলো ডিফল্টভাবে বন্ধ কি না পরীক্ষা করুন। এরপর একটি পরিষ্কার ব্রাউজার প্রোফাইল বা নতুন অ্যাপ ইনস্টলে একটি সম্পূর্ণ ব্যবহারকারী প্রবাহ চালান এবং লগে সঠিক পরিবেশের লেবেল আছে কি না নিশ্চিত করুন।

Related posts