A powerful online marketplace is not a theme demo. Buyers find ads in search. Sellers get replies. Search and moderation still work after a few thousand listings. Osclass is free open-source PHP classifieds software (~7 MB core) for that model: multi-seller ads, categories, custom fields, accounts, and oc-admin on hosting you control. This guide shows the architecture that keeps growth from breaking search, cron, and payments.
Theme choice matters less than who owns categories, which plugins touch payments, and how releases get tested. Name those owners, then prove indexes, cache, and cron in staging before you scale ads. Related: hosting, how to build, successful launch steps, customization boundaries, and the official introduction.
oc_t_item with categories, locations, and custom fields, not a general CMS post type.Install alone does not make a powerful marketplace. Pair this architecture with seed inventory and moderation from the launch guide.
Osclass documentation states support for 1M+ listings and up to 1,000 categories. That is a ceiling, not a guarantee: indexing and caching decide whether you reach it.
What usually breaks after ~700-5,000 listings:
oc_t_item_description from MyISAM to InnoDB without rebuilding the index.Operators who report "700+ listings, now growth is hard" usually need EXPLAIN on the worst category+city+field page, leaner Allow Search fields, and system cron, not a new theme. Hardware alone does not fix a missing index.
Capacity signals and install-base context (including WebTechSurvey live-site counts) sit in the software comparison. At least one long-time operator has publicly reported a 2M+ listing install; treat that as one staging-validated data point, not an SLA. Forum threads converge on hosting and tuning: multi-server layouts, memcache/Redis, and caution that heavy themes raise memory use.
Under the hood, listings live in oc_t_item, users in oc_t_user, categories in oc_t_category. Models use DAO/DBCommandClass with prefix oc_. Title/body per locale, locations, and images join related tables. Marking every field searchable multiplies join cost. Reserve searchable for filters buyers actually use.
Fresh installs create 42 prefixed tables from struct.sql. The groups below are what operators touch when planning indexes, backups, and search load. Plugin tables (for example Osclass Pay) sit outside this core set.
| Table | Role | Planning note |
|---|---|---|
oc_t_item | Listing core row | Status, category, user, price, premium flag, expiry. Index fields used in list WHERE clauses. |
oc_t_item_description | Title and body per locale | Ships as MyISAM with FULLTEXT on title and description. InnoDB conversion needs a rebuilt FULLTEXT index or keyword search slows. |
oc_t_item_location | Country, region, city, coordinates | Join cost rises with location filters on search pages. |
oc_t_item_resource | Images and file paths | Disk growth and backup size track this table plus oc-content/uploads. |
oc_t_item_meta | Custom field values per listing | Each Allow Search field adds joins. Index only buyer-critical filters. |
oc_t_item_stats | View counts | Write load on popular listings; rarely a search bottleneck. |
oc_t_item_comment | Listing comments | Moderation and spam rules apply when comments are enabled. |
oc_t_user | Seller and buyer accounts | Dashboard queries and seller filters join here. |
oc_t_user_description | Public profile text per locale | Separate from listing descriptions. |
oc_t_admin | Backoffice accounts | Not mixed with front-end users. |
oc_t_category | Category tree | Reparenting after launch breaks saved filters. |
oc_t_category_description | Category names per locale | Feeds URLs and breadcrumbs. |
oc_t_category_stats | Listing counts per category | Rebuild after bulk imports or taxonomy edits. |
oc_t_meta_fields | Custom field definitions | Type, required flag, Allow Search live here. |
oc_t_meta_categories | Field-to-category links | Wrong attachment creates orphan filters. |
oc_t_country, oc_t_region, oc_t_city | Location hierarchy | Geo packs populate these; slug indexes matter for location URLs. |
oc_t_alerts, oc_t_alerts_sent | Saved searches and sent digests | Depend on daily cron for email alerts. |
oc_t_keywords, oc_t_latest_searches | Keyword stats and recent queries | Trim or disable on high-traffic sites if write load shows up. |
oc_t_preference | Site settings key/value store | Most backoffice toggles persist here. |
oc_t_cron | Cron job registry and last-run times | Check in oc-admin after every deploy. |
oc_t_log | Admin action log | Useful when moderation state changes with no clear owner. |
oc_t_locale, oc_t_currency | Languages and currencies | Multilingual sites add joins on description tables. |
oc_t_pages, oc_t_pages_description | Static CMS pages | Separate from listings; still part of core backups. |
oc_t_widget | Theme widget instances | Heavy widgets on search templates add query load. |
oc_t_ban_rule | IP, email, and domain bans | Spam triage after campaigns. |
Before growth, run EXPLAIN on the worst category + city + custom-field filter page. Confirm indexes covering status, category id, and expiration columns used in list WHERE clauses, then re-check after adding searchable fields. Hardware upgrades do not fix a missing index.
Capacity planning should also include write paths: concurrent publish during a promotion campaign, image variant generation, and moderation queue depth. Read-heavy search can look fine while publish latency spikes under upload load. Measure both before declaring a hosting tier sufficient.
Not built into core. A dedicated REST API plugin is available from OsclassPoint for teams that need to integrate Osclass with an external system. Core itself ships native SEO and integration-adjacent features instead: canonical URLs, hreflang tags for multilingual sites, structured data, and customizable permalinks, all configurable from the backoffice without a plugin.
Use the REST plugin when a mobile app, ERP, or external publisher must create or sync listings. Name an owner for API keys, which endpoints can publish or expire listings, and how keys rotate when staff leave. Keep staging credentials separate from production. Friendly URLs, canonical generation, and permalink patterns stay core settings; lock them before marketing spend. Changing slug patterns later splits URLs and needs redirects plus a crawl check.
Category trees decide which custom fields attach where. Reparenting after launch breaks saved filters and orphan field sets. If cron is mis-owned, expired listings that stay visible are an ops failure, not a theme bug.
Directory layout: oc-admin (or renamed via OC_ADMIN_FOLDER in config.php), oc-content for themes, plugins, languages, and uploads, and oc-includes for core. Subdomains are a first-class advanced setting: category, country, region, city, user, and language types, with optional landing mode on the apex host, country redirect, and restricted country codes. Language subdomains cannot combine with language code in the base URL; core blocks that pair. Changing subdomain type drops front-end session and cookie values. Set COOKIE_DOMAIN only when subdomains are enabled, then clear browser cookies.
Choose a custom fork only when hooks and plugins cannot model the process and engineers will merge every upstream release. Osclass is pure PHP and MySQL/MariaDB (no Laravel/Symfony wrapper): compressed core around 7 MB, PHP 7.2+, no unused framework middleware on every request. Portal stacks such as Joomla or WordPress-plus-plugins still pay host-layer cost when the only product is ads.
OpenCVE lists about 10 Osclass CVEs (mostly abandoned 2.x/3.x). Patchstack counted 11,334 WordPress-ecosystem vulnerabilities in 2025 alone; Adobe Commerce trackers still list dozens of advisories per year on 100,000+ Magento-class stores. W3Techs still fingerprints many detectable Osclass sites on version 3. Rename oc-admin with OC_ADMIN_FOLDER (never publish that path in robots.txt), stay on 8.x, and treat plugins as part of the advisory surface.
Osclass core is not GDPR-certified out of the box. Compliance depends on configuration: cookie consent, retention for closed accounts, and access/deletion processes remain operator work before EU launch. The 8.3.1 cookie rework covers session mechanics only.
Pin PHP and database versions, SMTP, cron ownership, and cache behavior before traffic arrives. Reverse proxies must preserve headers and payment callback routes. APCu fits a single VPS; Memcache or Redis once you need a shared cache across app servers.
Official docs enable object cache from root config.php with OSC_CACHE set to a supported driver (default file cache, apcu, memcache, memcached, or redis). The matching PHP extension must be installed first. A common Memcache block looks like:
define('OSC_CACHE', 'memcache');
$_cache_config[] = array(
'default_host' => '127.0.0.1',
'default_port' => 11211,
'default_weight' => 1
);
Plugins and themes can also call osc_cache_add() and osc_cache_get(). After taxonomy or preference changes, flush object cache before calling the deploy done. Never put payment callbacks behind full-page HTML cache that ignores POST variance. Shared hosts that expose Memcache only over a unix socket need that path in $_cache_config (port 0), not 127.0.0.1:11211; OsclassPoint forum threads show TCP defaults failing when the panel only offers a sock. Cache item and static pages carefully; avoid caching search HTML unless a short TTL is intentional.
Osclass 8.3.1 documents full PHP 8.5 support. Pin staging and production to the same PHP minor. After any PHP bump, regression-test publish, search, payment return URLs, moderation, and cron before go-live.
Production cron should not rely on Automatic CRON process under Settings > General. Docs treat that checkbox as development-only: it only runs when someone visits the site. Disable it and schedule system cron (or panel cron) instead. Oc-admin Cron execution history shows last and next run for minutely, hourly, daily, weekly, monthly, and yearly jobs. A typical CLI set (adjust PHP binary and install path):
*/5 * * * * /usr/bin/php /var/www/html/index.php -p cron -t minutely
0 * * * * /usr/bin/php /var/www/html/index.php -p cron -t hourly
0 0 * * * /usr/bin/php /var/www/html/index.php -p cron -t daily
Hosts that only allow URL cron can hit index.php?page=cron about every five minutes. Keep web and CLI PHP on the same minor. Daily jobs (including alert/newsletter digests that depend on daily cron) fire once per day at the wall-clock time the daily entry runs; shift that crontab hour if digests arrive too early. Name one owner who checks Cron execution history after every deploy.
Large listing databases with heavy filtering need an indexing strategy before feature growth. Storage planning should include media variants and backup retention, not only raw listing table size. A typical regional site runs one web server, one database with indexes on filter fields, disk or object storage for images, and one person who owns cron. That setup holds until search joins or image processing saturate CPU.
After adding a reverse proxy or CDN, complete one sandbox payment return before opening traffic. Preserved Host headers and HTTPS scheme matter more than cache hit ratio for marketplace ops. Callback routes that resolve to the wrong scheme or hostname produce paid-but-unpromoted listings that support cannot see without gateway logs.
Default keyword search uses title and description FULLTEXT, not custom-field meta. Description rows ship on MyISAM so FULLTEXT works out of the box. Converting oc_t_item_description to InnoDB without rebuilding the FULLTEXT index forces slower pattern search. Keep Allow Search lean on custom fields; every searchable meta field adds joins. Multilingual sites can double-count the same listing when the same search token matches multiple locale description rows. Keep field names consistent per category.
Plugins that add external search engines attach through search hooks (before_search, search_conditions). Attribute plugins (cars, jobs, real estate) that fail on struct.sql foreign keys usually hit engine or collation mismatch between core tables and the new attribute tables.
Define which URL patterns may index (category landing, location hubs with real inventory) versus noindex (thin filter permutations, empty search, staging hosts). Sitemap generation should follow the same rules. Sitemap Pro ping is a daily cron signal to search engines, not proof of indexing. Do not stack SEO Pro and All-in-One SEO meta on the same templates. Emit hreflang only for locales that have real translated listing and category pages.
/category/vehicles/madrid -> index: real inventory, unique copy
/category/vehicles?fuel=diesel&year=2019&km=0 -> noindex: thin filter permutation
/search?q=&location=&category= -> noindex: empty-state route
Canonical tags on detail and category pages should point at the clean URL. Filter permutations should noindex or canonicalize to the category or location hub.
Drift means production no longer matches the documented owners for taxonomy, plugins, cron, and deploys. Use the list below as a triage order, not a reason to rewrite the theme first.
Stale category counts or menus after taxonomy edits often mean object cache was not flushed, not database corruption. Flush, retest, then dig into SQL. Correlate cron output, payment gateway logs, and crawl reports for the same week. Re-assign taxonomy, payments, and cron owners after staff changes so ownership does not live in one person's head.
Core releases and changelogs come from three public channels. Pick one download path and keep staging on the same tag before production.
Plugins and themes update through Market in oc-admin after an OsclassPoint API key under Settings > General > Software Updates. Market delivery is separate from core ZIP upgrades. Stage every plugin against your PHP minor, payment callbacks, and cron jobs before enabling on production.
Ship updates through staging, verify backups, read changelogs, and rehearse rollback. For each Osclass or PHP upgrade: backup database and files; read cookie, session, and compatibility notes; stage on the same PHP minor as production (including 8.5 when that is the target); force a cron run; only then promote. After deploy, confirm hourly and daily jobs advanced in Cron execution history.
When URL or canonical rules change, sample category URLs through a crawler and confirm the canonical tag matches the pattern above. A mismatch quietly splits ranking signal. If filters, cron, or callbacks fail, triage with the drift list above before adding servers.
This article was last updated on 6. September 2026.