নো-কোড ব্যাকএন্ডের জন্য মাল্টি-টেন্যান্ট SaaS ডেটা মডেল অপশন
মাল্টি-টেন্যান্ট SaaS ডেটা মডেল নির্বাচন নিরাপত্তা, রিপোর্টিং এবং পারফরম্যান্স নির্ধারণ করে। `tenant_id`, পৃথক স্কিমা এবং পৃথক ডেটাবেসের স্পষ্ট ট্রেডঅফগুলো তুলনা করুন।

সমস্যা: টেন্যান্টদের আলাদা রাখা কিন্তু পারফরম্যান্স ধীর করা ছাড়া\n\nমাল্টি-টেন্যান্সি মানে একটা সফটওয়্যার প্রোডাক্ট অনেক কাস্টমার (টেন্যান্ট) সার্ভ করে, এবং প্রতিটি টেন্যান্ট শুধু তাদের নিজস্ব ডেটা দেখতে পারবে। কঠিন অংশ হল এটা ধারাবাহিকভাবে করা: শুধু এক স্ক্রিনেই নয়, বরং প্রতিটি API কল, অ্যাডমিন প্যানেল, এক্সপোর্ট এবং ব্যাকগ্রাউন্ড জবে।\n\nআপনার ডেটা মডেল দৈনন্দিন অপারেশনে প্রত্যাশার চেয়েও বেশি প্রভাব ফেলে। এটা পারমিশন, রিপোর্টিং, কুয়েরির গতি যখন আপনি বড় হচ্ছেন, এবং একটি “সামান্য” বাগ কতটা ঝুঁকিপূর্ণ হতে পারে—সবকিছুকে গঠন করে। একটা ফিল্টার মিস করলে ডেটা লিক হতে পারে। খুব বেশি আলাদা করলে রিপোর্টিং ঝামেলার হয়ে যাবে।\n\nমাল্টি-টেন্যান্ট SaaS ডেটা মডেল সাজাতে সাধারণত তিনটি উপায় প্রচলিত:\n\n- প্রতিটি টেবিলে tenant_id সহ একক ডেটাবেস\n- প্রতিটি টেন্যান্টের জন্য একই ডেটাবেসের ভেতরে পৃথক স্কিমা\n- প্রতিটি টেন্যান্টের জন্য পৃথক ডেটাবেস\n\nআপনি যদি নো-কোড ব্যাকএন্ডে ভিজ্যুয়ালি বিল্ড করেও থাকেন, একই ট্রেডঅফ প্রযোজ্য। AppMaster-এর মত টুলগুলো আপনার ডিজাইন থেকে বাস্তবে ব্যাকএন্ড কোড এবং ডেটাবেস স্ট্রাকচার জেনারেট করে, ফলে প্রারম্ভিক মডেলিং সিদ্ধান্তগুলো দ্রুত প্রোডাকশনে প্রকাশ পায়।\n\nএকটি হেল্পডেস্ক টুল কল্পনা করুন। যদি প্রতিটি টিকেট সারিতে tenant_id থাকে, তাহলে "সব ওপেন টিকেট" কুয়েরি করা সহজ, কিন্তু আপনাকে সর্বত্র টেন্যান্ট চেক জোরদার করতে হবে। যদি প্রতিটি টেন্যান্টের আলাদা স্কিমা বা ডেটাবেস থাকে, তাহলে ডিফল্টে আইসোলেশন শক্তিশালী হয়, কিন্তু ক্রস-টেন্যান্ট রিপোর্টিং (যেমন "সব কাস্টমারের গড় ক্লোজ টাইম") আরও কাজ নেয়।\n\nলক্ষ্য এমন আলাদা করা যা আপনি বিশ্বাস করতে পারবেন—রিপোর্টিং, সাপোর্ট এবং স্কেলিং-এ ঘন্টার ফ্রিকশান বাড়ানোর বিনিময়ে নয়।\n\n## দ্রুত পছন্দ করার উপায়: ৪টি প্রশ্ন যা উত্তর সংকুচিত করে\n\nডেটাবেস থিওরিতে দিয়ে শুরু করবেন না। শুরু করুন প্রডাক্ট কীভাবে ব্যবহার হবে এবং আপনাকে সাপ্তাহিকভাবে কি অপারেট করতে হবে তা থেকে।\n\n### চারটি প্রশ্ন যা সাধারণত উত্তর স্পষ্ট করে দেয়\n\n1) ডেটা কতটা সংবেদনশীল এবং আপনি কি কঠোর নিয়মের আওতায় আছেন? স্বাস্থ্যসেবা, ফাইন্যান্স এবং কঠোর কাস্টমার কনট্র্যাক্ট সাধারণত শক্তিশালী আইসোলেশনের (পৃথক স্কিমা বা পৃথক ডেটাবেস) দিকে ঠেলে দেয়। এটা ঝুঁকি কমায় এবং অডিট সহজ করে।\n\n2) আপনাকে কি ঘন ঘন ক্রস-টেন্যান্ট রিপোর্টিং করতে হবে? যদি নিয়মিতভাবে "সব কাস্টমার" মেট্রিক (ব্যবহার, রাজস্ব, পারফরম্যান্স) দরকার হয়, তবে tenant_id সহ একটি একক ডেটাবেস সাধারণত সবচেয়ে সহজ। পৃথক ডেটাবেসগুলো এটা কঠিন করে তোলে কারণ আপনাকে অনেক জায়গা থেকে কুয়েরি করে ফলাফল মিলাতে হবে।\n\n3) টেন্যান্টগুলো একে অপরের থেকে কতটা আলাদা হবে? যদি টেন্যান্টদের কাস্টম ফিল্ড, কাস্টম ওয়ার্কফ্লো বা ইউনিক ইন্টিগ্রেশন দরকার হয়, তাহলে পৃথক স্কিমা বা ডেটাবেস পরিবর্তনগুলো অন্যদের উপর ছড়ানোর সম্ভাবনা কমায়। যদি বেশিরভাগ টেন্যান্ট একই স্ট্রাকচার শেয়ার করে, তাহলে tenant_id পরিষ্কার থাকে।\n\n4) আপনার দল বাস্তবে কি পরিচালনা করতে পারবে? বেশি আইসোলেশন সাধারণত বেশি কাজ: বেশি ব্যাকআপ, বেশি মাইগ্রেশন, বেশি মুভিং পার্টস এবং ব্যর্থতার বেশি জায়গা।\n\nপ্রায়োগিক উপায় হলো আপনার শীর্ষ দুইটি অপশন প্রোটোটাইপ করা, তারপর আসল ব্যথা-বিন্দুগুলো পরীক্ষা করা: পারমিশন নিয়ম, রিপোর্টিং কুয়েরি, এবং মডেল পরিবর্তনের সময় কি করে রোলআউট হয়।\n\n## পদ্ধতি 1: প্রতিটি রোতে tenant_id সহ একটিয ডেটাবেস\n\nএটাই সবচেয়ে সাধারণ সেটআপ: সব কাস্টমার একটাই টেবিল শেয়ার করে এবং প্রতিটি টেন্যান্ট-অবজেক্টের রেকর্ডে tenant_id থাকে। অপারেশনালি সহজ কারণ আপনার একটাই ডেটাবেস এবং এক সেট মাইগ্রেশন চলে।\n\nনীতিটি কঠোর: যদি একটি রো কোনো টেন্যান্টের হয়, সেটিতে অবশ্যই tenant_id থাকতে হবে এবং প্রতিটি কুয়েরি সেটি দিয়ে ফিল্টার করতে হবে। টেন্যান্ট-অধিকারিত টেবিলগুলো সাধারণত users, roles, projects, tickets, invoices, messages, file metadata এবং টেন্যান্ট ডেটা সংযোগকারী join টেবিলগুলো থাকে।\n\nলিকগুলো কমাতে tenant_id কে অম্য করুণ:\n\n- টেন্যান্ট-অবজেক্ট টেবিলগুলোতে tenant_id প্রয়োজনীয় (NOT NULL) করুন\n- tenant_id দিয়ে শুরু হওয়া ইনডেক্স যোগ করুন (উদাহরণ: tenant_id, created_at)\n- ইউনিক নিয়মে tenant_id অন্তর্ভুক্ত করুন (যেমন, প্রতি টেন্যান্টে ইমেইল ইউনিক)\n- tenant_id প্রতিটি API ও বিজনেস ফ্লোতে পাস করুন, শুধু UI ফর্মেই নয়\n- এটিকে শুধু ক্লায়েন্ট-সাইড ফিল্টারে নয়, ব্যাকএন্ডে প্রয়োগ করুন\n\nPostgreSQL-এ row-level security পলিসি একটি শক্তিশালী সেফটি নেট যোগ করতে পারে, বিশেষ করে যখন কুয়েরি ডাইনামিক্যালি জেনারেট হয়।\n\nরেফারেন্স ডেটা সাধারনত দুইটি বালতিতে পড়ে: শেয়ারড টেবিল (যেমন countries) যেখানে tenant_id নেই, এবং টেন্যান্ট-স্কোপড ক্যাটালগ (যেমন কাস্টম ট্যাগ বা পাইপলাইন) যেখানে tenant_id আছে।\n\nআপনি যদি AppMaster দিয়ে নির্মাণ করেন, একটা সাধারণ অভ্যাস বেশিরভাগ ইনসিডেন্ট প্রতিরোধ করে: যে কোনও create বা read এর আগে Business Process লজিকে প্রমাণীকৃত ব্যবহারকারীর টেন্যান্ট থেকে tenant_id সেট করুন এবং সেই প্যাটার্নটি ধারাবাহিক রাখুন।\n\n## পারমিশনের প্রভাব: প্রতিটি পদ্ধতিতে কী বদলে যায়\n\nপারমিশনগুলোই হল যেখানে মাল্টি-টেন্যান্সি সফল বা ব্যর্থ হয়। আপনি যে ডেটা লেআউট বেছে নেবেন তা ব্যবহারকারীর স্টোরিং, কুয়েরি স্কোপিং এবং অ্যাডমিন স্ক্রিনে “উপস” মুহূর্ত এড়ানোর পদ্ধতি পরিবর্তন করে।\n\nএকক ডেটাবেস এবং প্রতিটি রোতে tenant_id থাকলে টিমগুলো প্রায়ই একটি শেয়ারড Users টেবিল ব্যবহার করে এবং প্রতিটি ব্যবহারকারীকে একটি টেন্যান্ট ও এক বা একাধিক রোলে যুক্ত করে। বড় নিয়ম একই থাকে: প্রতিটি রিড ও রাইটে টেন্যান্ট স্কোপ থাকা জরুরি, এমনকি ছোট টেবিল যেমন settings, tags, বা logs এর ক্ষেত্রেও।\n\nপৃথক স্কিমা হলে প্রায়ই শেয়ারড আইডেন্টিটি লেয়ার থাকে (লগইন, পাসওয়ার্ড, MFA) এবং টেন্যান্ট ডেটা প্রতিটি টেন্যান্টের স্কিমায় থাকে। পারমিশনগুলো আংশিকভাবে রাউটিং সমস্যা হয়ে যায়: অ্যাপকে ব্যবসায়িক লজিক চালানোর আগে সঠিক স্কিমার ওপর কুয়েরি পয়েন্ট করতে হবে।\n\nপৃথক ডেটাবেসে আইসোলেশন সবচেয়ে শক্তিশালী, কিন্তু পারমিশন লজিক ইনফ্রাস্ট্রাকচারে সরে যায়: সঠিক ডেটাবেস সংযোগ নির্বাচন, ক্রেডেনশিয়াল ম্যানেজমেন্ট, এবং "গ্লোবাল" স্টাফ অ্যাকাউন্ট হ্যান্ডল করা।\n\nসব তিনটি পদ্ধতিতে কয়েকটি প্যাটার্ন ধারাবাহিকভাবে ক্রস-টেন্যান্ট ঝুঁকি কমায়:\n\n- সেশনে বা অথ টোকেনে tenant_id রাখুন এবং এটিকে বাধ্যতামূলক হিসেবে বিবেচনা করুন।\n- টেন্যান্ট চেকগুলো এক জায়গায় কেন্দ্রীকৃত করুন (মিডলওয়্যার বা একটি শেয়ারড Business Process), ন্যায় বিচ্ছুরিত নয়।\n- অ্যাডমিন টুলগুলোতে টেন্যান্ট কনটেক্সট স্পষ্ট দেখান এবং একটি অভিন্ন টেন্যান্ট-সুইচ আবশ্যক করুন।\n- সাপোর্ট অ্যাক্সেসের জন্য ইম্পারসনেশন ব্যবহার করুন এবং অডিট লগ রাখুন।\n\nAppMaster-এ এটির অর্থ সাধারণত প্রমাণীকরণের পরে টেন্যান্ট কনটেক্সট স্টোর করা এবং API এন্ডপয়েন্ট ও Business Processes-এ সেটি পুনঃব্যবহার করা, যাতে প্রতিটি কুয়েরি স্কোপড থাকে। সাপোর্ট এজেন্ট কেবল তখনই অর্ডার দেখতে পারবে যখন অ্যাপ টেন্যান্ট কনটেক্সট সেট করেছে, UI শুধু ফিল্টার করায় নয়।\n\n## tenant_id মডেলে রিপোর্টিং ও পারফরম্যান্স\n\ntenant_id সহ একক-ডেটাবেস পদ্ধতিতে রিপোর্টিং সাধারণত সরল। গ্লোবাল ড্যাশবোর্ড (MRR, সাইনআপ, ব্যবহার) একটি একক কুয়েরি চালিয়ে চলে, এবং টেন্যান্ট-লেভেল রিপোর্ট একই কুয়েরি একটি ফিল্টারসহ।\n\nট্রেডঅফ হল সময়ের সাথে পারফরম্যান্স। টেবিলগুলোর আকার বাড়লে একটি ব্যস্ত টেন্যান্ট অনেক রো তৈরি করে, বেশি রাইট ট্রিগার করে এবং সাধারণ কুয়েরিগুলো ধীর করে দিতে পারে যদি ডাটাবেস অনেক স্ক্যান করতে হয়।\n\nইনডেক্সিং এই মডেলকে সুস্থ রাখে। অধিকাংশ টেন্যান্ট-স্কোপড রিড এমন ইনডেক্স ব্যবহার করতে পারা উচিত যা tenant_id দিয়ে শুরু হয়, যাতে ডাটাবেস সরাসরি ঐ টেন্যান্টের অংশে লাফাতে পারে।\n\nভালো বেসলাইন:\n\n- যৌগিক ইনডেক্স যোগ করুন যেখানে tenant_id প্রথম কলাম (উদাহরণ: tenant_id + created_at, tenant_id + status, tenant_id + user_id)\n- যেখানে ক্রস-টেন্যান্ট কুয়েরি দরকার নয়, সত্যিকারের গ্লোবাল ইনডেক্স কম রাখুন\n- এমন জয়েন ও ফিল্টারের দিকে নজর রাখুন যা tenant_id ভুলে যায়—এসব ধীর স্ক্যান করে দেয়\n\nরিটেনশন ও ডিলিটের পরিকল্পনাও দরকার কারণ এক টেন্যান্টের ইতিহাস সবার জন্য টেবিল ফুল করে দিতে পারে। যদি টেন্যান্টদের আলাদা রিটেনশন পলিসি থাকে, সফট ডিলিট সহ টেন্যান্ট-ভিত্তিক আরকাইভিং বা পুরানো রো এক্সপোর্ট করে tenant_id ভিত্তিক আর্কাইভ টেবিলে স্থানান্তর করার কথা ভাবুন।\n\n## পদ্ধতি 2: টেন্যান্টভিত্তিক পৃথক স্কিমা\n\nপৃথক স্কিমা ব্যবহারে আপনি এখনও একটি PostgreSQL ডেটাবেস ব্যবহার করেন, কিন্তু প্রতিটি টেন্যান্টকে একটি নিজস্ব স্কিমা (উদাহরণ: tenant_42) দেওয়া হয়। সেই স্কিমার ভিতরের টেবিলগুলো কেবল ঐ টেন্যান্টের জন্যই। এটি প্রতিটি কাস্টমারকে একটি “মিনি ডেটাবেস” দেওয়ার মত অনুভব করায়, কিন্তু অনেক ডেটাবেস চালানোর ওভারহেড ছাড়াই।\n\nএকটি সাধারণ সেটআপে গ্লোবাল সার্ভিসগুলো একটি শেয়ারড স্কিমায় থাকে এবং টেন্যান্ট ডেটা টেন্যান্ট স্কিমাগুলিতে থাকে। ভাগাভাগি সাধারণত কী শেয়ার করা দরকার এবং কী কখনো মিশবে না তার ওপর নির্ভর করে।\n\nসাধারণ বিভাজন:\n\n- শেয়ারড স্কিমা: tenants টেবিল, প্ল্যান, বিলিং রেকর্ড, ফিচার ফ্ল্যাগ, অডিট সেটিংস\n- টেন্যান্ট স্কিমা: বিজনেস টেবিল যেমন orders, tickets, inventory, projects, custom fields\n- নির্দিষ্ট ক্ষেত্রে (প্রোডাক্টের ওপর নির্ভর করে): users এবং roles, বিশেষ করে যদি ব্যবহারকারী একাধিক টেন্যান্ট অ্যাক্সেস করতে পারে\n\nএই মডেল ক্রস-টেন্যান্ট জয়েনের ঝুঁকি কমায় কারণ টেবিলগুলো ভিন্ন নামস্পেসে থাকে। এটি একটি স্কিমা টার্গেট করে ব্যাকআপ বা রিস্টোর করা সহজও করে।\n\nমাইগ্রেশনগুলো দলগুলোকে চমকে দেয়। যখন আপনি নতুন টেবিল বা কলাম যোগ করেন, আপনাকে প্রতিটি টেন্যান্ট স্কিমায় পরিবর্তন প্রয়োগ করতে হবে। 10 টেন্যান্ট হলে এটা ম্যানেজ করা যায়; 1,000 টেন্যান্ট হলে আপনাকে স্কিমা সংস্করণ ট্র্যাক করা, ব্যাচে মাইগ্রেশন চালানো এবং নিরাপদ ব্যর্থতার প্রক্রিয়া নিশ্চিত করার প্রয়োজন হবে।\n\nশেয়ারড সার্ভিসগুলো যেমন auth এবং billing সাধারণত টেন্যান্ট স্কিমার বাইরে থাকে। একটি বাস্তব পদক্ষেপ হল শেয়ারড auth (একটা user টেবিল এবং টেন্যান্ট মেম্বারশিপ টেবিল) এবং শেয়ারড billing (Stripe কাস্টমার ID, ইনভয়েস), আর টেন্যান্ট স্কিমাগুলোতে টেন্যান্ট-অধিকারিত বিজনেস ডেটা রাখা।\n\nAppMaster ব্যবহার করলে, প্রথম থেকেই পরিকল্পনা করুন কিভাবে Data Designer মডেলগুলো শেয়ারড বনাম টেন্যান্ট স্কিমায় ম্যাপ হবে, এবং গ্লোবাল সার্ভিসগুলো স্থিতিশীল রাখুন যাতে টেন্যান্ট স্কিমাগুলো লগইন বা পেমেন্ট ভেঙ্গে না দেয়।\n\n## পৃথক স্কিমা নিয়ে রিপোর্টিং ও পারফরম্যান্স\n\nপৃথক স্কিমা ডিফল্টভাবে tenant_id-এ চেয়ে শক্তিশালী আলাদা প্রদান করে কারণ টেবিলগুলো আলাদা। পারমিশন স্কিমা-লেভেলে সেট করা যায়।\n\nযদি বেশিরভাগ রিপোর্ট টেন্যান্ট-ভিত্তিক হয়, তাহলে রিপোর্টিং সেখানে দুর্দান্ত। কুয়েরিগুলো সরল থাকে কারণ আপনি প্রতিটি টেন্যান্টের টেবিল থেকে পড়েন, বারবার শেয়ারড টেবিল ফিল্টার করার প্রয়োজন পড়ে না। এই মডেল "বিশেষ" টেন্যান্টকে অতিরিক্ত টেবিল বা কাস্টম কলাম দেওয়ার সুবিধাও দেয়, অন্যদেরকে সেই বোঝা বহন করতে হয় না।\n\nসমষ্টিগত ক্রস-টেন্যান্ট রিপোর্টিংই যেখানে স্কিমা সমস্যার সৃষ্টি করে। আপনাকে হয় অনেকগুলো স্কিমায় কুয়েরি চালাতে হবে এমন একটি রিপোর্টিং লেয়ার দরকার, বা একটি শেয়ারড সামারি টেবিল রক্ষা করতে হবে।\n\nসাধারণ প্যাটার্নগুলো:\n\n- প্রতি-টেন্যান্ট ড্যাশবোর্ড যা কেবল ঐ টেন্যান্টের স্কিমা থেকে কুয়েরি করে\n- একটি সেন্ট্রাল অ্যানালিটিক্স স্কিমা যেখানে প্রতিটি টেন্যান্ট থেকে রাতভরে রোলআপ করা হয়\n- এক্সপোর্ট জব যা টেন্যান্ট ডেটাকে ওয়্যারহাউস-ফ্রেন্ডলি ফরম্যাটে কপি করে\n\nপারফরম্যান্স সাধারণত টেন্যান্ট-লেভেল কাজের জন্য শক্ত। ইনডেক্সগুলো প্রতিটি টেন্যান্টে ছোট থাকে, এবং এক স্কিমায় ভারী রাইট অন্যদের প্রভাবিত করার সম্ভাবনা কম। ট্রেডঅফ হচ্ছে অপারেশনাল ওভারহেড: নতুন টেন্যান্ট প্রোভিশনিং মানে একটি স্কিমা তৈরি, মাইগ্রেশন চালানো এবং প্রতিটি স্কিমা সমন্বয় রাখার কাজ।\n\nযখন আপনি tenant_id থেকে শক্তিশালী আইসোলেশন চান কিন্তু অনেক ডেটাবেস চালাতে চান না, তখন স্কিমা ভালো মানায়, বা যখন আপনি প্রত্যাশা করেন টেন্যান্ট অনুযায়ী কাস্টমাইজেশন লাগবে।\n\n## পদ্ধতি 3: প্রতিটি টেন্যান্টের জন্য পৃথক ডেটাবেস\n\nপ্রত্যেক কাস্টমারকে তাদের নিজস্ব ডেটাবেস (বা একই সার্ভারে আলাদা ডেটাবেস) দিলে এটা সবচেয়ে আলাদা উপায়: যদি এক টেন্যান্টের ডেটা করাপ্ট হয়, কনফিগারেশন ভুল হয় বা লোড বাড়ে, তাহলে অন্যদের ওপর প্রভাব পড়ার সম্ভাবনা খুব কম।\n\nএটি নিবন্ধভুক্ত পরিবেশ (স্বাস্থ্য, ফাইন্যান্স, সরকার) বা এন্টারপ্রাইজ কাস্টমারের জন্য ভালো যেখানে কঠোর আলাদা থাকার, কাস্টম রিটেনশন নিয়ম, বা ডেডিকেটেড পারফরম্যান্স প্রয়োজন।\n\nঅনবোর্ডিং একটি প্রোভিশনিং ওয়ার্কফ্লো হয়ে ওঠে। নতুন টেন্যান্ট সাইন আপ করলে আপনার সিস্টেমকে একটি ডেটাবেস তৈরি বা ক্লোন করতে হবে, বেস স্কিমা প্রয়োগ করতে হবে (টেবল, ইনডেক্স, কনস্ট্রেইন্ট), ক্রেডেনশিয়াল নিরাপদে তৈরি ও সংরক্ষণ করতে হবে এবং সঠিক ডেটাবেসে API অনুরোধ রুট করতে হবে।\n\nAppMaster দিয়ে নির্মাণ করলে, মূল ডিজাইন সিদ্ধান্ত হচ্ছে টেন্যান্ট ডিরেক্টরি কোথায় রাখা হবে (টেন্যান্ট থেকে ডেটাবেস কানেকশনের ম্যাপ) এবং কীভাবে নিশ্চিত করা হবে যে প্রতিটি অনুরোধ সঠিক কানেকশন ব্যবহার করছে।\n\nআপগ্রেড ও মাইগ্রেশন প্রধান ট্রেডঅফ। একটি স্কিমা পরিবর্তন আর একবার চালানো নয়—এটি প্রতিটি টেন্যান্টের জন্য চালাতে হবে। তাই এটি অপারেশনালি বেশি কাজ এবং ঝুঁকি বাড়ায়, তাই দলগুলো প্রায়ই স্কিমা ভার্সন করে এবং প্রতিটি টেন্যান্টে নিয়ন্ত্রিত কাজ হিসেবে মাইগ্রেশন চালায়।\n\nউপকার হলো নিয়ন্ত্রণ: বড় টেন্যান্টদের আগে মাইগ্রেট করে পারফরম্যান্স পর্যবেক্ষণ করতে পারেন, তারপর ধাপে ধাপে পরিবর্তন রোল আউট করতে পারেন।\n\n## পৃথক ডেটাবেস নিয়ে রিপোর্টিং ও পারফরম্যান্স\n\nপৃথক ডেটাবেসগুলো বোঝার দিক থেকে সহজ। আকস্মিক ক্রস-টেন্যান্ট রিড কমই ঘটে এবং কোন পারমিশন ভুল সাধারণত শুধুই একটি টেন্যান্টকে প্রভাবিত করে।\n\nপারফরম্যান্সও শক্তি। ভারী কুয়েরি, বড় ইম্পোর্ট বা একটি টেন্যান্টে রানওয়ে রিপোর্ট অন্যদের ধীর করে না। এটা noisy neighbor থেকে ভালো সুরক্ষা দেয় এবং প্রতিটি টেন্যান্টের জন্য রিসোর্স টিউন করতে সুবিধা দেয়।\n\nট্রেডঅফ রিপোর্টিং-এ পড়ে। গ্লোবাল অ্যানালিটিক্স সবচেয়ে কঠিন কারণ ডেটা শারীরিকভাবে বিভক্ত। কাজ করা প্যাটার্নগুলো হল মূল ইভেন্ট বা টেবিলগুলো সেন্ট্রাল রিপোর্টিং ডেটাবেসে কপি করা, ইভেন্টগুলো একটি ওয়্যারহাউসে পাঠানো, প্রতিটি টেন্যান্টের রিপোর্ট চালিয়ে ফলাফল একত্র করা (যখন টেন্যান্ট সংখ্যা কম), এবং প্রোডাক্ট মেট্রিক্স আলাদা রাখা কাস্টমার ডেটা থেকে।\n\nঅপারেশনাল খরচ আরেক প্রধান ফ্যাক্টর। বেশি ডেটাবেস মানে বেশি ব্যাকআপ, আপগ্রেড, মনিটরিং এবং ইনসিডেন্ট রেসপন্স। কানেকশন লিমিটও দ্রুত পৌঁছে যেতে পারে কারণ প্রতিটি টেন্যান্ট নিজস্ব কানেকশন পুল চাইতে পারে।\n\n## সাধারণ ভুলগুলো যা ডেটা লিক বা পরে কষ্ট দেয়\n\nঅধিকাংশ মাল্টি-টেন্যান্ট সমস্যা বড় ডিজাইন ফেইলকরা নয়। সেগুলো ছোট উপেক্ষিত জিনিস যা পরে সিকিউরিটি বাগ, জটিল রিপোর্টিং এবং ব্যয়বহুল ক্লিনআপে পরিণত হয়। মাল্টি-টেন্যান্সি কাজ করে যখন টেন্যান্ট আলাদা রাখাকে অভ্যাস হিসেবে দেখা হয়, পরে বোল্ট-অন ফিচার হিসেবে নয়।\n\nএকটি সাধারণ লিক হল একটি টেবিলে টেন্যান্ট ফিল্ড ভুলে যাওয়া, বিশেষ করে join টেবিলগুলো যেমন user_roles, invoice_items, বা tags। সবকিছু ঠিকঠাক দেখে লাগতে পারে যতক্ষণ না কোনো রিপোর্ট বা সার্চ সেই টেবিল জয়েন করে এবং অন্য টেন্যান্টের রো টেনে আনে।\n\nআরেকটি প্রায়শই সমস্যা হল অ্যাডমিন ড্যাশবোর্ডগুলো যা টেন্যান্ট ফিল্টার বাইপাস করে। এটি প্রায়ই "শুধু সাপোর্টের জন্য" শুরু হয়, তারপর পুনরায় ব্যবহার করা হয়। নো-কোড টুলগুলো এখানে কোনও ঝুঁকি বদলায় না: প্রতিটি কুয়েরি, বিজনেস প্রসেস এবং এন্ডপয়েন্ট যা টেন্যান্ট ডেটা পড়ে তাদের একই টেন্যান্ট স্কোপ দরকার।\n\nআইডি-রাও মুখে আঘাত করতে পারে। যদি আপনি টেন্যান্টদের মধ্যে হিউম্যান-ফ্রেন্ডলি আইডি শেয়ার করেন (যেমন order_number = 1001) এবং ধরে নেন এগুলো গ্লোবালি ইউনিক, সাপোর্ট টুল ও ইন্টিগ্রেশনগুলো রেকর্ড মিক্স করবে। টেন্যান্ট-স্কোপড আইডেন্টিফায়ারগুলোকে ইন্টারনাল প্রাইমারি কী থেকে পৃথক রাখুন এবং লুকআপে টেন্যান্ট কনটেক্সট অন্তর্ভুক্ত করুন।\n\nশেষে, দলগুলো মাইগ্রেশন ও ব্যাকআপকে কম মূল্যায়ন করে যখন তারা বড় হয়। 10 টেন্যান্টে সহজ যা 1,000 টেন্যান্টে ধীর ও ঝুঁকিপূর্ণ হয়ে যায়।\n\nদ্রুত চেকগুলো যা বেশিরভাগ ব্যথা প্রতিরোধ করে:\n\n- প্রতিটি টেবিলে টেন্যান্ট মালিকানা স্পষ্ট করুন, join টেবিলগুলোসহ।\n- একটি টেন্যান্ট স্কোপিং প্যাটার্ন ব্যবহার করুন এবং সেটি সব জায়গায় পুনরায় ব্যবহার করুন।\n- রিপোর্ট ও এক্সপোর্টগুলো টেন্যান্ট স্কোপ ছাড়া চালানো যাবে না (যদি সত্যিই গ্লোবাল না হয়)।\n- API ও সাপোর্ট টুলে টেন্যান্ট-অসম্পষ্ট আইডি ব্যবহার এড়ান।\n- বৃদ্ধি পেলে রিস্টোর ও মাইগ্রেশন ধাপগুলো আগে অনুশীলন করুন, পরে না।\n\nউদাহরণ: একটি সাপোর্ট এজেন্ট "invoice 1001" সার্চ করে ভুল টেন্যান্টের রেকর্ড টেনে আনলে এটা ছোট বাগ নয়—এর বড় প্রভাব আছে।\n\n## চুক্তি করার আগে একটি দ্রুত চেকলিস্ট\n\nমাল্টি-টেন্যান্ট SaaS ডেটা মডেলে চূড়ান্ত সিদ্ধান্ত নেওয়ার আগে কয়েকটি পরীক্ষা চালান। লক্ষ্য হল ডেটা লিক আগে ধরাও এবং নিশ্চিত করা যে আপনার পছন্দটি টেবিল বড় হওয়ার পরও কাজ করবে।\n\n### এক দিনে করা যায় এমন দ্রুত পরীক্ষা\n\n- ডেটা আইসোলেশন প্রুফ: দুইটি টেন্যান্ট (A এবং B) তৈরি করুন, একই রকম রেকর্ড যোগ করুন, তারপর নিশ্চিত করুন প্রতিটি রিড ও আপডেট সক্রিয় টেন্যান্টের স্কোপেই সীমাবদ্ধ। কেবল UI ফিল্টারে اعتماد করবেন না।\n- পারমিশন ব্রেক টেস্ট: Tenant A ব্যবহারকারীর হিসেবে লগইন করে কেবল রেকর্ড ID বদলায় Tenant B রেকর্ডটি খোলা/এডিট/ডিলিট করতে চেষ্টা করুন। যদি কিছুতে সাফল্য মেলে, সেটিকে রিলিজ ব্লকর হিসেবে বিবেচনা করুন।\n- রাইট-পাথ সেফটি: ব্যাকগ্রাউন্ড জব, ইমপোর্ট বা অটোমেশন থেকেও নতুন রেকর্ডগুলো সঠিক টেন্যান্ট মান পায় কি না নিশ্চিত করুন (বা সঠিক স্কিমা/ডেটাবেসে যায়)।\n- রিপোর্টিং ট্রায়াল: নিশ্চিত করুন আপনি টেন্যান্ট-নির্দিষ্ট রিপোর্ট এবং "সমস্ত টেন্যান্ট" রিপোর্ট (ইন্টার্নাল স্টাফের জন্য) করতে পারেন, এবং কারা গ্লোবাল ভিউ দেখতে পারবে তা স্পষ্ট নিয়ম অনুযায়ী আছে।\n- পারফরম্যান্স চেক: এখনই ইনডেক্স স্ট্র্যাটেজি যোগ করুন (বিশেষ করে (tenant_id, created_at) এবং অন্যান্য কমন ফিল্টারগুলোর জন্য) এবং ইচ্ছাকৃতভাবে অন্তত একটি ধীর কুয়েরি মাপুন যাতে আপনি জানেন খারাপ কেমন দেখায়।\n\nরিপোর্টিং টেস্টকে কংক্রিট করতে দুইটি প্রশ্ন নিন যেগুলো আপনি জানেন দরকার হবে (একটি টেন্যান্ট-স্কোপড, একটি গ্লোবাল) এবং স্যাম্পল ডেটায় চালান।\n\nsql\n-- টেন্যান্ট-নির্দিষ্ট: শেষ ৩০ দিন, একটি টেন্যান্ট\nSELECT count(*)\nFROM tickets\nWHERE tenant_id = :tenant_id\n AND created_at \u003e= now() - interval '30 days';\n\n-- গ্লোবাল (অ্যাডমিন): টেন্যান্টগুলোর তুলনা\nSELECT tenant_id, count(*)\nFROM tickets\nWHERE created_at \u003e= now() - interval '30 days'\nGROUP BY tenant_id;\n\n\nআপনি যদি AppMaster-এ প্রোটোটাইপ করেন, এসব চেকগুলোকে আপনার Business Process ফ্লোতে (read, write, delete) তৈরি করুন এবং Data Designer-এ দুইটি টেন্যান্ট সিড করুন। যখন এই টেস্টগুলো রিয়ালিস্টিক ডেটার ভলিউমে পাস করবে, আপনি আত্মবিশ্বাস নিয়ে সিদ্ধান্ত নিতে পারবেন।\n\n## উদাহরণ দৃশ্য: প্রথম কাস্টমার থেকে স্কেল আপ করা\n\nএকটি ২০-জনের কোম্পানি কাস্টমার পোর্টাল চালু করছে: ইনভয়েস, টিকেট, এবং একটি সরল ড্যাশবোর্ড। তারা প্রথম মাসে 10টি টেন্যান্ট প্রত্যাশা করে, এবং এক বছরে 1,000-এ পৌঁছানোর পরিকল্পনা রাখে।\n\nশুরুর দিকে সবচেয়ে সহজ মডেল সাধারণত একক ডেটাবেস যেখানে গ্রাহক ডেটা রাখে এমন প্রতিটি টেবিলে tenant_id থাকে। এটা দ্রুত তৈরি করা যায়, রিপোর্ট করা সহজ এবং ডুপ্লিকেট সেটআপ এড়ায়।\n\n10 টেন্যান্টের সঙ্গে সবচেয়ে বড় ঝুঁকি পারফরম্যান্স নয়; সেটা পারমিশন। একটি মিস করা ফিল্টার (উদাহরণ: "লিস্ট ইনভয়েস" কুয়েরি যা tenant_id ভুলে যায়) ডেটা লিক করতে পারে। দলটি উচিত টেন্যান্ট চেকগুলো এক স্থানে জোরদার করা (শেয়ারড বিজনেস লজিক বা পুনরায় ব্যবহারযোগ্য API প্যাটার্ন) এবং টেন্যান্ট স্কোপিং অমান্য করা যাবে না বলে ধরতে হবে।\n\n10 থেকে 1,000 তে যাওয়ার সময় চাহিদাগুলো বদলে যায়। রিপোর্টিং ভারী হয়, সাপোর্ট "এই টেন্যান্টের সব এক্সপোর্ট করে দিন" চাইতে পারে, এবং কিছু বড় টেন্যান্ট শেয়ারড টেবিলকে দমন করে ধীর করে দিতে পারে।\n\nএকটি বাস্তবিক আপগ্রেড পথ সাধারণত এভাবে দেখা যায়:\n\n1) একই অ্যাপ লজিক ও পারমিশন নিয়ম রাখুন, কিন্তু উচ্চ-ভলিউম টেন্যান্টগুলোকে পৃথক স্কিমায় সরান।\n2) সবচেয়ে বড় টেন্যান্ট(বা কপ্লায়েন্স ক্লায়েন্ট)দের আলাদা ডেটাবেসে স্থানান্তর করুন।\n3) একটি শেয়ারড রিপোর্টিং লেয়ার রাখুন যা সব টেন্যান্ট থেকে পড়ে, এবং ভারী রিপোর্টগুলো অফ-পিকে শিডিউল করুন।\n\nআজকের দিনেই দেয়ার তুলনায় সহজতম মডেল বেছে নিন যা আজ ডেটা নিরাপদ রাখে, তারপর "কয়েকটি বিশাল টেন্যান্ট" সমস্যার জন্য মাইগ্রেশন পরিকল্পনা রাখুন—শুরুতেই তার জন্য অপ্টিমাইজ করবেন না।\n\n## পরবর্তী পদক্ষেপ: একটি মডেল বেছে নিন এবং নো-কোড ব্যাকএন্ডে প্রোটোটাইপ করুন\n\nপ্রথমত রক্ষা করতে চান কী: ডেটা আইসোলেশন, অপারেশনাল সরলতা, না কি টেন্যান্ট-লেভেল স্কেলিং। আত্মবিশ্বাস আসে একটি ছোট প্রোটোটাইপ বানিয়ে এবং বাস্তব পারমিশন ও রিপোর্টিং কেস দিয়ে একে ভাঙ্গার চেষ্টা করে।\n\nসহজ শুরু নির্দেশিকা:\n\n- যদি বেশিরভাগ টেন্যান্ট ছোট এবং আপনি সহজ ক্রস-টেন্যান্ট রিপোর্টিং চান, একক ডেটাবেস ও প্রতিটি রোতে tenant_id দিয়ে শুরু করুন।\n- যদি একটু শক্তিশালী আলাদা চান কিন্তু একটি ডেটাবেস ম্যানেজ করতে চান, টেন্যান্টভিত্তিক পৃথক স্কিমা বিবেচনা করুন।\n- যদি টেন্যান্টরা কঠোর আইসোলেশন দাবি করে (কপ্লায়েন্স, ডেডিকেটেড ব্যাকআপ, noisy-neighbor), তাহলে পৃথক ডেটাবেস বিবেচনা করুন।\n\nবিল্ড করার আগে টেন্যান্ট সীমানাগুলো সাদাসরল ভাষায় লিখে নিন। রোলগুলো (owner, admin, agent, viewer) এবং তারা কী করতে পারবে তা নির্ধারণ করুন, এবং কি "গ্লোবাল" ডেটা মানে (plans, templates, audit logs) তা স্পষ্ট করুন। রিপোর্টিং কিভাবে কাজ করবে তা ঠিক করুন: শুধু টেন্যান্ট-ভিত্তিক, না কি ইন্টার্নাল স্টাফের জন্য “সব টেন্যান্ট” থাকা দরকার—এগুলো আগে সিদ্ধান্ত নিন।\n\nযদি আপনি AppMaster ব্যবহার করছেন, আপনি এই প্যাটার্নগুলো দ্রুত প্রোটোটাইপ করতে পারেন: Data Designer-এ টেবিল মডেল করুন (tenant_id, ইউনিক কনস্ট্রেইন্ট এবং আপনার কুয়েরিগুলো যে ইনডেক্সের উপর নির্ভর করবে), তারপর Business Process Editor-এ নিয়মEnforce করুন যাতে প্রতিটি রিড ও রাইট টেন্যান্ট-স্কোপড থাকে। যদি প্ল্যাটফর্মের রেফারেন্স পয়েন্ট চান, AppMaster উপলব্ধ আছে appmaster.io-এ।\n\nএকটি বাস্তবিক শেষ পরীক্ষা: দুটি টেন্যান্ট (A ও B) তৈরি করুন, একই রকম ইউজার ও অর্ডার যোগ করুন, এবং একই ফ্লো দুটির জন্য চালান। Tenant A-এর জন্য রিপোর্ট এক্সপোর্ট করুন, তারপর ইচ্ছাকৃতভাবে Tenant B আইডি পাঠিয়ে একই এন্ডপয়েন্টে চেষ্টা করুন। আপনার প্রোটোটাইপ তখনই “পর্যাপ্তভাবে সুরক্ষিত” যখন এসব চেষ্টা প্রতিবার ব্যর্থ হয় এবং আপনার মেইন রিপোর্টগুলো রিয়ালিস্টিক ডেটা সাইজে দ্রুত চলে।
প্রশ্নোত্তর
সাধারণত অপারেশন সহজ রাখতে এবং ক্রস-টেন্যান্ট অ্যানালিটিক্স ঘন ঘন দরকার হলে ডিফল্ট হিসেবে একক ডেটাবেস যেখানে প্রতিটি টেন্যান্ট-অবজেক্টে tenant_id থাকে, তা বেছে নিন। শক্তিশালী আলাদা আইসোলেশন বা টেন্যান্ট-ভিত্তিক কাস্টমাইজেশন চাইলে পৃথক স্কিমা বিবেচনা করুন। যদি কপ্লায়েন্স বা এন্টারপ্রাইজ চাহিদা কঠোর হয় এবং পারফরম্যান্স কন্ট্রোল দরকার হয়, তবে পৃথক ডেটাবেস নির্বাচন করুন।
ব্যাকএন্ডে টেন্যান্ট স্কোপিংকে বাধ্যতামূলক হিসেবে বিবেচনা করুন, UI ফিল্টারের উপর নির্ভর করবেন না। টেন্যান্ট-অধিকারিত টেবিলগুলোতে tenant_id নন-নাল করে দিন এবং ক্লায়েন্ট ইনপুট বিশ্বাস না করে সর্বদা প্রমাণীকৃত ব্যবহারকারীর কনটেক্স্ট থেকে tenant_id সংগ্রহ করুন। যদি পরিবেশে ফিট করে, PostgreSQL-এর row-level security-র মতো সেফটি নেট যোগ করুন, এবং পরীক্ষাগুলো বানান যা শুধুমাত্র ID বদল করে অন্য টেন্যান্টের রেকর্ড অ্যাক্সেস করার চেষ্টা করে।
কমন ফিল্টারগুলোর জন্য এমন ইনডেক্স তৈরি করুন যাতে tenant_id প্রথম কলাম হয়, যাতে ডাটাবেস সহজে নির্দিষ্ট টেন্যান্টের ডেটা খুঁজে পায়। সময়ভিত্তিক ভিউগুলোর জন্য (tenant_id, created_at) একটি সাধারণ বেসলাইন। অ্যাপের ড্যাশবোর্ড ফিল্টারগুলোর জন্য (tenant_id, status) বা (tenant_id, user_id) যোগ করুন। ইউনিক কনস্ট্রেইন্টগুলোও টেন্যান্ট-স্কোপড করুন (যেমন, প্রতি টেন্যান্টে ইমেইল ইউনিক)।
পৃথক স্কিমা আংশিকভাবে ক্রোস্টেন্যান্ট জয়েন ভুল করা থেকে রক্ষা করে কারণ টেবিলগুলো ভিন্ন নামস্পেসে থাকে, এবং আপনি স্কিমা লেভেলে পারমিশন সেট করতে পারেন। প্রধান অসুবিধা হচ্ছে মাইগ্রেশন: প্রতিটি স্কিমায় একই পরিবর্তন প্রয়োগ করতে হবে, এবং টেন্যান্ট সংখ্যা বাড়লে এটা প্রসেস-ওরিয়েন্টেড কাজ হয়ে ওঠে। যদি আপনি tenant_id-এর চেয়ে কঠোর আলাদা থাকা চান কিন্তু অনেকগুলো ডেটাবেস চালাতে না চান, তাহলে স্কিমা একটি ভালো মধ্যপথ।
পৃথক ডেটাবেস ব্লাস্ট রেডিয়াস ছোট করে: কোন পারফরম্যান্স স্পাইক, কনফিগারেশন ভুল বা করাপশন হলে সেটি সাধারণত একটি টেন্যান্টেই সীমাবদ্ধ থাকে। খরচ হচ্ছে অপারেশনাল ওভারহেড: প্রোভিশনিং, ব্যাকআপ, মনিটরিং এবং মাইগ্রেশনগুলো টেন্যান্ট সংখ্যার সাথেই গুণতে থাকে। প্রতিটি API কল সঠিক ডেটাবেস কানেকশনে রুট করা নিশ্চিত করার জন্য একটি নির্ভরযোগ্য টেন্যান্ট ডিরেক্টরি ও রাউটিং প্রয়োজন।
একক ডেটাবেস ও tenant_id-এ গ্লোবাল রিপোর্টিং সহজ: সেক্ষেত্রে গ্লোবাল ড্যাশবোর্ডগুলো কেবল টেন্যান্ট ফিল্টার ছাড়া একই কুয়েরি। স্কিমা বা পৃথক ডেটাবেস হলে সাধারণ প্যাটার্ন হচ্ছে মুখ্য ইভেন্ট বা সামারি ডেটা একটি শেয়ার্ড রিপোর্টিং স্টোরে কপি করা বা শিডিউলকৃত রোলআপ রাখা, যাতে ক্রস-টেন্যান্ট অ্যানালিটিক্স সম্ভব হয়। নিয়মটা রাখুন সহজ: প্রোডাক্ট-ওয়াইড মেট্রিক্স রিপোর্টিং লেয়ারে পাঠান, আর টেন্যান্ট ডেটা আলাদা রাখুন।
সাপোর্ট টুলগুলোতে টেন্যান্ট কনটেক্সট স্পষ্ট রাখুন এবং রেকর্ড দেখার আগে একটি ইস্যু-স্পষ্ট টেন্যান্ট-সুইচ বাধ্যত করুন। ইম্পারসনেশন ব্যবহার করলে কারা কখন কী দেখেছে তা অডিট লগ রাখুন এবং সময়সীমাবদ্ধ করুন। এমন সাপোর্ট ওয়ার্কফ্লো এড়ান যা কেবল রেকর্ড আইডি নেয় বাগের কারণ হয়ে ওঠে (যেমন “invoice 1001” সমস্যা)।
টেন্যান্ট-ভিত্তিক কাস্টমাইজেশনের প্রয়োজনে স্কিমা বা আলাদা ডেটাবেস ব্যবহার করলে এক টেন্যান্টের পরিবর্তন অন্যদের প্রভাবিত করার সম্ভাবনা কমে। যদি অধিকাংশ টেন্যান্ট একরকম থাকে, একক মডেল রেখে tenant_id দিয়ে কাজ করুন এবং পার্থক্যগুলো ফিচার ফ্ল্যাগ বা অপশনাল ফিল্ড দিয়ে ম্যানেজ করুন। মূল কথা: এমন টেবিল তৈরি করবেন না যা স্পষ্টভাবে নয় যে শেয়ারড না টেন্যান্ট-স্পেসিফিক।
টেন্যান্ট সীমানা আগে থেকেই ডিজাইন করুন: প্রমাণীকরণের পরে টেন্যান্ট কনটেক্সট কোথায় রাখা হবে তা ঠিক করে নিন এবং প্রতিটি রিড/রাইট সেটি ব্যবহার করবে—এটাই নিরাপদ প্যাটার্ন। AppMaster-এ সাধারণত এটি মানে: প্রমাণীকরণের পরে tenant_id সেট করে Business Process-এ ব্যবহার করা, যাতে এন্ডপয়েন্টগুলো ভুল করে টেন্যান্ট-স্কোপ ছাড়াই কাজ না করে। এটিকে প্রতিটি স্ক্রিনে আলাদাভাবে পুনরায় নির্মাণ করবেন না—এটি একটি পুনঃব্যবহারযোগ্য প্যাটার্ন হিসেবে প্রয়োগ করুন।
একই ধরনের ডেটা নিয়ে দুইটি টেন্যান্ট তৈরি করে আইসোলেশন ভঙ্গ করার চেষ্টা করুন: কেবল রেকর্ড আইডি বদলে অন্য টেন্যান্টের ডেটা পড়া/আপডেট/ডিলিট করা যায় কি না পরীক্ষা করুন। ব্যাকগ্রাউন্ড জব, ইমপোর্ট, এবং এক্সপোর্টগুলোও সঠিক টেন্যান্ট স্কোপে লেখে কিনা নিশ্চিত করুন—এই পাথগুলোই সহজে ভোলা হয়। পাশাপাশি রিয়েলিস্টিক স্যাম্পল ভলিউমে একটি টেন্যান্ট-লেভেল রিপোর্ট এবং একটি গ্লোবাল অ্যাডমিন রিপোর্ট চালিয়ে পারফরম্যান্স পরীক্ষা করুন।


