زیادہ تر لوگ جو ڈراپ شپنگ اسٹور کھولتے ہیں، وہ شارٹ کٹس کی تلاش میں ہوتے ہیں۔ وہ کامیاب مصنوعات کی تلاش میں فورمز دیکھتے ہیں، سستے ورچوئل اسسٹنٹ ہائر کرتے ہیں، اور امید کرتے ہیں کہ الگورتھم انہیں راتوں رات امیر بنا دے گا۔ مجھے یہ چیزیں کبھی پرکشش نہیں لگیں۔ میں نے ڈراپ شپنگ کو ایک انجینئرنگ کے مسئلے کے طور پر دیکھا۔ میں جلدی پیسہ کمانے کے پیچھے نہیں تھا۔ میں انوینٹری سنکنگ کے مسائل حل کرنا چاہتا تھا، ایسے پرائسنگ الگورتھم بنانا چاہتا تھا جو مارکیٹ کی حقیقی تبدیلیوں کے مطابق ردعمل دیں، اور اپنی ذہنی سکون کو داؤ پر لگائے بغیر سپلائر APIs کے ساتھ کام کرنا چاہتا تھا۔ اسٹور تو Node.js اور PostgreSQL کا استعمال کرتے ہوئے بنائے گئے میرے سسٹم کا ایک ضمنی اثر (side effect) بن گیا۔

اسٹور کو بیک اینڈ سروس کی طرح سمجھیں

جس لمحے آپ ڈراپ شپنگ کو مارکیٹنگ کی جدوجہد کے بجائے ایک ڈسٹری بیوٹڈ سسٹمز (distributed systems) کے چیلنج کے طور پر دیکھنا شروع کر دیتے ہیں، مسائل دلچسپ ہو جاتے ہیں۔ آپ اسٹور فرنٹ کو کیسے درست رکھتے ہیں جب تین مختلف سپلائرز آپ کے اسٹاک کو کنٹرول کر رہے ہوں؟ آپ قیمتوں کو مسابقتی کیسے رکھتے ہیں جب وہی سپلائرز آپ کو بتائے بغیر اپنی لاگت تبدیل کر دیتے ہیں؟ آپ ایک ایسے کیٹلاگ کو کیسے سنبھالتے ہیں جو پچاس SKUs سے بڑھ کر پانچ ہزار تک پہنچ جائے، وہ بھی اسپریڈ شیٹس میں ڈوبے بغیر؟

میں نے ان سوالات کے جوابات کے لیے ایک پائپ لائن بنائی۔ Node.js نے ایونٹ ڈریون آرکیٹیکچر کو سنبھالا کیونکہ مجھے ایک وقت میں متعدد سپلائر کنکشنز کو سنبھالنے کے لیے نان بلاکنگ I/O کی ضرورت تھی۔ PostgreSQL نے ڈیٹا کے مستند ذریعے (source of truth) کے طور پر کام کیا۔ مجھے اسکیمہ ڈیزائن (schema design) کی بہت فکر تھی کیونکہ ایک غیر منظم انوینٹری ٹیبل اس وقت ایک ڈراونا خواب بن جاتا ہے جب آپ پہلی بار ایسی چیز زیادہ بیچ دیتے ہیں جو موجود ہی نہیں ہے۔

پائپ لائن بنانا

بنیادی کام بیان کرنا سادہ تھا: سپلائر APIs سے پروڈکٹ ڈیٹا حاصل کرنا۔ عملی طور پر، اس کا مطلب تھا SKUs، تفصیلات، تصاویر، اسٹاک کی سطح، اور قیمتوں کو ان اینڈ پوائنٹس سے حاصل کرنا جو ایک دوسرے سے بات کرنے کے لیے کبھی ڈیزائن ہی نہیں کیے گئے تھے۔ میں نے Node.js میں پولنگ سروسز لکھیں جو وقفے وقفے سے سپلائر فیڈز سے ڈیٹا حاصل کرتی تھیں۔ ہر آنے والے پے لوڈ (payload) کو ہمارے اندرونی اسٹور فرنٹ ڈیٹا بیس تک پہنچنے سے پہلے ویلیڈیشن اور میپنگ لیئرز سے گزرنا پڑتا تھا۔

میں نے PostgreSQL کو پروڈکٹس، ویریئنٹ، پرائسنگ ہسٹری، اور سنک لاگز کے لیے الگ الگ ٹیبلز کے ساتھ ترتیب دیا۔ جب کسی سپلائر نے خاموشی سے کسی فیلڈ کا نام تبدیل کیا یا وہاں 'null' بھیج دیا جہاں پہلے نمبر ہوا کرتا تھا، تو پائپ لائن نے اسے پکڑ لیا اور اسٹور فرنٹ کے ڈیٹا کو خراب کرنے کے بجائے ایک فیلر ریکارڈ لکھ دیا۔ میں ایک لاگ رو (log row) دیکھ کر بالکل جان سکتا تھا کہ کون سا اینڈ پوائنٹ خراب ہوا، یہ کب ہوا، اور کون سی فیلڈز غلط تھیں۔ اس آبزرویبلٹی (observability) نے مجھے ایک سے زیادہ بار بچایا جب کسی سپلائر نے ویک اینڈ پر اپنے API کو "اپ گریڈ" کرنے کا فیصلہ کیا۔

کیا چیزیں بہتر رہیں

آٹومیشن نے بہت زیادہ وقت بچایا۔ شروع میں، میں نے دستی طریقہ اپنایا: سپلائر کی اسپریڈ شیٹس ڈاؤن لوڈ کرنا، انہیں ہاتھ سے صاف کرنا، تصاویر کو فارمیٹ کرنا، اور اسٹور پر CSVs اپ لوڈ کرنا۔ جب کیٹلاگ چند درجن اشیاء سے تجاوز کر گیا تو یہ ناممکن ہو گیا۔ خودکار پائپ لائن نے نئی لسٹنگز، قیمتوں کی اپ ڈیٹس، اور اسٹاک کی تبدیلیوں کو اس طرح سنبھالا کہ مجھے دوبارہ کبھی اسپریڈ شیٹ کو چھونے کی ضرورت نہیں پڑی۔

پروڈکٹ کی تفصیلات کو بڑے پیمانے پر تیار کرنا ٹیمپلیٹس کے ذریعے ممکن ہوا۔ پانچ سو تقریباً ایک جیسی اشیاء کے لیے منفرد تحریر لکھنا قابل عمل نہیں ہے۔ اس کے بجائے، میں نے ایک ٹیمپلیٹنگ لیئر بنائی جو سپلائر کے ایٹریبیوٹس جیسے کہ میٹریل، ڈائمینشنز، یا رنگ کو لے کر انہیں ترتیب وار ڈسکرپشن بلاکس میں شامل کر دیتی تھی۔ اس کا آؤٹ پٹ اتنا صاف تھا کہ اسے استعمال کرنا آسان تھا اور اتنا مستقل مزاج تھا کہ ایک ہزار نئے SKUs شامل کرنے کے لیے کسی دستی کاپی رائٹنگ کی ضرورت نہیں پڑی۔

قیمتوں کی نگرانی بھی میری توقعات سے بڑھ کر رہی۔ میں نے ایک ہلکی پھلکی مانیٹرنگ لیئر بنائی جو اہم مصنوعات کے ایک مخصوص حصے پر حریفوں کی قیمتوں پر نظر رکھتی تھی۔ جب اس نے قیمتوں میں تبدیلی محسوس کی، تو سسٹم نے میرے طے کردہ حدود (guardrails) کے اندر خود بخود ہمارے مارجنز کو ایڈجسٹ کر دیا۔ اگر کسی سپلائر نے ہول سیل قیمت کم کی، تو لسٹنگ کی قیمت دنوں کے بجائے منٹوں میں اس تبدیلی کی عکاسی کر سکتی تھی۔ اس فوری ردعمل نے کم مارجن والی اشیاء پر نمایاں فرق ڈالا۔

کیا چیزیں خراب ہوئیں اور کیوں

سپلائر APIs میں تسلسل (consistency) کی کمی ہوتی ہے۔ یہ کوئی شکایت نہیں ہے؛ یہ ایک حقیقت ہے۔ ایک پارٹنر صاف ستھرا JSON فراہم کرتا ہے جس میں قابل پیش گوئی پیجینیشن (pagination) ہوتی ہے۔ دوسرا پیر کو camelCase ٹیگز کے ساتھ XML بھیجتا ہے اور بدھ کو snake_case۔ ریٹ لمٹس (rate limits) بہت زیادہ سے لے کر بہت کم تک مختلف ہوتی ہیں۔ ڈاؤن ٹائم (downtime) کا پتہ مناسب اسٹیٹس کوڈز کے بجائے HTML ایرر پیجز کے ذریعے چلتا ہے۔ آپ کو ایسے اینڈ پوائنٹس کے لیے دفاعی پارسرز (defensive parsers) اور ری ٹرائی لاجک (retry logic) لکھنی پڑتی ہے جو ایسا برتاؤ کرتے ہیں جیسے انہیں 2003 میں ڈیزائن کیا گیا ہو۔

انوینٹری سنک (Inventory sync) میں ایسی race conditions تھیں جنہوں نے میری نیندیں اڑا دیں۔ ذرا تصور کریں: دو صارفین ایک دوسرے کے چند سیکنڈ کے اندر آخری یونٹ کا آرڈر دے دیتے ہیں، یا کوئی سپلائر webhook آپ کو بالکل اسی لمحے بتاتا ہے کہ اسٹاک ختم ہو چکا ہے جب کوئی خریدار checkout پر کلک کرتا ہے۔ میرا ابتدائی read-then-update لاجک بری طرح ناکام ہو گیا۔ مجھے ہائی ویلوسٹی SKUs کے لیے atomic PostgreSQL transactions اور pessimistic locking کا استعمال کرتے ہوئے سنک لیئر کو دوبارہ لکھنا پڑا۔ یہ concurrency کا ایک تکلیف دہ اور عملی سبق تھا جس کے لیے کوئی بھی ٹیٹوریل آپ کو اس طرح تیار نہیں کر سکتا جیسے کہ جب اصل رقم داؤ پر لگی ہو۔

میری سب سے بڑی ناکامی کسٹمر سپورٹ آٹومیشن کو نظر انداز کرنا تھا۔ میں ڈیٹا پائپ لائنز کے پیچھے پاگل تھا اور انسانی اثرات کو محض ایک ضمنی چیز سمجھتا تھا۔ آرڈرز دیر سے پہنچے۔ سپلائرز نے غلط رنگ بھیجے۔ صارفین نے ای میلز بھیجیں جو میرے ان باکس میں گھنٹوں پڑی رہیں جبکہ میں API timeouts کو ڈی بگ کر رہا تھا۔ میرے پاس نہ تو ticket routing تھی، نہ خودکار جوابات، اور نہ ہی chatbot handoffs۔ تکنیکی انفراسٹرکچر مضبوط تھا۔ انسانی انفراسٹرکچر غائب تھا، اور اس خلا نے کاروبار کو اس سے کہیں زیادہ نقصان پہنچایا جتنا کہ کسی غیر مستحکم webhook نے کبھی پہنچایا تھا۔

ایک انجینئر کی طرح تصاویر کی ٹیسٹنگ کرنا

میں نے پروڈکٹ کی تصاویر پر ایک ضمنی تجربہ کیا۔ میں نے session-based bucketing سے منسلک سادہ URL parameter routing کا استعمال کرتے ہوئے مختلف صارفین کو مختلف hero images دکھائیں۔ ایک ورژن میں پروڈکٹ کو سادہ سفید پس منظر پر دکھایا گیا۔ دوسرے میں اسے ایک اصل ڈیسک پر lifestyle setting میں دکھایا گیا۔ میں نے آرڈر فلو سے براہ راست منسلک بنیادی event logging کا استعمال کرتے ہوئے ہر bucket کے لیے conversion rates کا سراغ لگایا۔

چھوٹی تبدیلیوں نے engagement کو بہتر بنایا۔ Lifestyle shots ہمیشہ نہیں جیتتے تھے، لیکن جب وہ جیتتے تھے، تو اس کا فائدہ اتنا نمایاں ہوتا تھا کہ میری ترجیحات بدل جائیں۔