পদ্ধতি · 2026-08-26 · 5 মিনিটে পড়ুন
How Chakri Khoj decides what counts as a live job
Every few weeks someone asks me — usually a friend of a friend, sometimes a journalist — how Chakri Khoj comes up with the number in the corner of our homepage. The specific number changes daily; the question doesn't. This post is the honest answer.
It matters because the wrong answer is easy and popular. I've read half a dozen articles claiming Bangladesh has "50,000+ jobs" or "sarkari job supply crashed by 40%" based on doing arithmetic on the highest and lowest job identifiers on a portal like Teletalk. Those numbers are wrong. Not because the writers are lazy — because the underlying identifiers weren't designed to be counted.
What a "live job" means on Chakri Khoj
A row in our database counts as live when three things are true at the same time:
- A real recruitment source published it. Not a rumour, not a screenshot, not an unsourced Facebook post. Every row on our site is traceable back to an official employer page, a government portal, or an established job aggregator — the sources are listed on /about.
- The deadline hasn't passed. If the source publishes an
end_date, we treat any row whereend_date >= todayas live. If noend_dateis published (some organisations don't), we keep the row visible until the source itself removes it. - We can point you at where to apply. Every live row has either an
apply_urlor adetail_url. Without one of those, a listing is decoration, not information.
Those three rules are baked into the SQL we run to power the homepage and the "closing this week" pages. Nothing marketing about it.
Why sequential job numbers are not the market
Here's the most common bad measurement I want to warn you off: subtracting the highest and lowest GJOB identifiers on Teletalk and calling the difference the number of jobs.
Every posting on Teletalk-hosted portals is assigned a database identifier that looks like GJOB14273. It's tempting to reason: "Today's highest is GJOB14552, and a year ago it was GJOB10000, so there were 4,552 government jobs this year."
Sequential identifiers can't be treated as a job count for four independent reasons:
- Gaps. Deleted posts, rejected drafts, and rolled-back transactions all consume identifiers without producing a job. Any auto-incrementing primary key has these gaps, in any database.
- Non-job rows. The same table sometimes stores training notices, exam schedules, and admin postings that share the identifier space.
- Expired records. Most of the 4,552 slots between GJOB10000 and GJOB14552 are circulars whose deadlines closed months ago. Expired ≠ live.
- Cross-references. A single job posting sometimes references other job IDs in its own description. The page for the Bangladesh Rural Development Board's
GJOB14273, for example, contains a reference toGJOB14282. The identifier space is entangled, not linear.
Statisticians call the general problem of estimating population size from observed identifiers the "German Tank Problem." Even the sophisticated version of that estimator only tells you how many identifiers were ever assigned — not how many jobs are active today, which is the number a job-seeker actually needs.
The only reliable way to count is what every honest job aggregator does: enumerate the live-listings page of each source, de-duplicate, filter to postings whose deadlines haven't passed. That's what our number reflects.
How we de-duplicate
The same job often appears on multiple sources — a Teletalk portal will list a Bangladesh Rural Development Board circular, and Bdjobs may syndicate the same one an hour later. We store rows keyed by (source, external_id) — a unique constraint enforced in the database. If the same external identifier arrives from the same source twice, the second write updates the first row rather than creating a duplicate.
When two different sources publish what is clearly the same job, we currently show both rows and let the reader choose which link to click. This isn't perfect. It errs on the side of over-showing rather than accidentally hiding a canonical circular under a wrong dedup key. That trade-off is one I'd change if enough readers tell me the duplicates are more annoying than useful.
How often we refresh
Government portals get scraped daily. Cron runs at 6:00 UTC (12:00 Bangladesh time), so a circular published at 9 a.m. Dhaka time shows up in our database within about three hours. New Teletalk portals — the government keeps quietly adding them — get discovered every Sunday morning. Private-sector employers get pulled on the same daily cycle where the source supports it, and on-demand when a reader tells us an employer we're missing has just posted a role.
Every job page also carries a last_seen_at timestamp internally. If we haven't seen a row on its source for two consecutive scrapes and its deadline has passed, we stop showing it.
Where I know we're not perfect
Three honest gaps as of August 2026:
- Multinational corporate careers (Unilever, Citi, and a handful of others) run on ATS platforms whose public APIs I've only just started integrating. Coverage there is thinner than I'd like.
- A few well-known Bangladesh employers hide their careers behind Cloudflare bot-checks or JavaScript-only portals. Registered in the codebase, not yet fetching.
- Bengali-language job descriptions that use Unicode punctuation I haven't normalised yet occasionally miss category matching. If your search misses something obvious, please tell me.
Corrections
If a listing on Chakri Khoj is wrong, missing, or a duplicate you want merged, email me at the address on /about with the URL and a one-line description of what's wrong. Corrections usually go live the same day.
— Abdullah M Akhand, Canada
সত্যিকারের সাপ্তাহিক ডাইজেস্ট চান?
প্রতি রবিবার সকালে: এই সপ্তাহে বন্ধ হওয়া বিজ্ঞপ্তি এবং একটি সম্পাদকের বাছাই, সরাসরি আপনার ইনবক্সে। কোনো সাইনআপ নেই, কোনো ডেটা শেয়ার নেই।
বিনামূল্যে ডেডলাইন এলার্ট সেট করুন