Magento development

Magento development: modules, integrations and B2B logic that survive the next upgrade

Whether a Magento extension is well built rarely shows on the day it is signed off, but at the next upgrade. Sharpness Solutions GmbH in Oldenburg, Germany, develops for Magento Open Source: custom modules built on plugins, observers and dependency injection rather than core changes, integrations with ERP, PIM and shipping, B2B features such as customer-specific prices and order approvals, themes and performance work. We also take over existing code and third-party extensions, review them and make them upgrade-safe. This page explains how a Magento module should be built, what Open Source provides out of the box and what it does not, and how to recognise an implementation that is still maintainable three years from now. Where an Adobe Commerce licence is already in place, we work with that too.

Make an enquiry 0441 21 21 63 0 Mon – Thu 9:00 – 16:00, Fri 9:00 – 13:00 (CET)

Where Magento shops stand when development begins

Some projects start from scratch; most start with a shop that has been trading for years, with modules from several hands, an ERP behind it and a list of requests from sales and purchasing. Six situations come up again and again. They have one thing in common: whatever was saved during the build comes back at the upgrade.

Someone has changed the core

A file in vendor/ was edited directly, a core class copied and adapted. It works until Composer restores the original file at the next update. Then the change has either silently disappeared or the update fails — and both usually come to light in the live shop.

Twenty extensions, and nobody knows them all

Modules from the Marketplace, from previous agencies, from copied code samples. Several plugins hook into the same method, two extensions replace the same class via a preference. Each module works on its own. Together, the load order decides which one wins.

The upgrade to 2.4.9 breaks extensions

In 2.4.9 Adobe replaced Zend_Cache with symfony/cache and Laminas MVC with its own MVC implementation, and PHP 8.5 is the only approved PHP version. Extensions built on these components have to be adapted. Find that out during the upgrade window and the upgrade gets postponed.

Shop and ERP show different stock levels

An import script runs overnight via cron, writes no log and stops at the first faulty record. Next morning prices or stock levels are wrong, and nobody knows since when. An integration without a log is a guess.

B2B customers want their own terms

Customer-specific prices, company accounts with several buyers, approvals before an order goes out. Adobe's B2B module belongs to Adobe Commerce and requires a separate licence. In Magento Open Source these features are built as custom modules — which is why they belong in the scope from day one.

Category pages are getting slower

More products, more variants, more store views. Indexers fall behind, message queue consumers stand still, the HTTP cache hardly gets a hit because one module marks every page as uncacheable. More servers fix none of this. A measure only pays off once it is clear where the time goes.

Custom modules: extending Magento where it is designed to be extended

Magento is built from modules, and custom functionality belongs in custom modules, not in the core. There are two intended ways to change existing behaviour. Plugins, also called interceptors, modify public methods before, after or around the call and are declared in di.xml; Magento generates the interceptor classes itself. Observers react to events dispatched by Magento or another module and are registered in events.xml, either globally or per area such as the storefront or the admin. We choose whichever touches least: an after plugin rather than an around plugin, an observer whenever a suitable event exists. The smaller the intervention, the smaller the check at the next upgrade.

A module receives its dependencies through dependency injection: the object manager supplies whatever is configured in di.xml. We do not inject the object manager itself, even though legacy code often does — it hides dependencies and makes testing harder. A preference, meaning a custom default implementation for an interface or class, is used only where no plugin will do. It replaces the original completely, and of several preferences for the same class only one wins. Towards the outside, a good module communicates through service contracts: PHP interfaces split into data interfaces for the data structures and service interfaces for the operations. Other modules, integrations and later extensions then depend on a contract, not on an implementation.

A module describes its tables and columns with declarative schema instead of the old upgrade scripts. Content that ships with the module — attributes, configuration, master data — is created by data patches; changes that cannot be expressed declaratively go into schema patches, and both can be made revertible where needed. Every module is checked against the Magento Coding Standard, a rule set for PHP_CodeSniffer. Deployment runs through Composer and Git, with bin/magento setup:upgrade, setup:di:compile and setup:static-content:deploy in production mode, never by uploading files by hand. The code sits in a Git repository that belongs to you, and every change can be traced. A module is finished only when another developer can read it without having to ask.

Third-party extensions and legacy code: reviewed and made upgrade-safe

Most Magento shops that come to us have a history: extensions from the Adobe Commerce Marketplace, free or paid, modules from previous agencies, small changes made directly in the code. So we start with an inventory of every module. Where does it come from, does anyone still maintain it, and which Magento and PHP versions is it built for? Which plugins, observers and preferences does it bring, which classes does it replace, where does it clash with other modules? Are there changes in vendor/ or copied core files? On top of that, the Coding Standard runs over the custom code, and setup:di:compile shows whether the whole thing compiles cleanly. The outcome is a list, not an opinion.

Each module then gets a decision: keep it, update it, replace it with a maintained alternative, rebuild it properly as a custom module, or remove it because nobody uses the feature any more. Core changes are moved out into custom modules, as plugins or observers, so that Composer has a free hand again at upgrade time. On tooling: according to Adobe, the Upgrade Compatibility Tool is available for Adobe Commerce instances only. For Magento Open Source we therefore check with the Coding Standard, the compiler, existing tests and a full run on a staging system with a copy of the live data. Marketplace access keys are tied to the edition, too; a key for Open Source does not work for Adobe Commerce. The cheapest upgrade check is the one for an extension that is no longer installed.

How much work an upgrade can mean for your extensions is clear from the step to 2.4.9. Adobe replaced Zend_Cache with symfony/cache and Laminas MVC with its own MVC implementation, raised the Symfony dependencies to 7.4 LTS and swapped TinyMCE for HugeRTE in the WYSIWYG editor. According to Adobe, extensions that use Zend_Cache must be adapted; anyone who has extended the editor needs to test against HugeRTE. For 2.4.9 only PHP 8.5 is approved. We adapt our own and inherited modules and check with the vendors of purchased extensions when compatible versions will be available. How upgrades, security patches and operation work as a whole is covered on our Magento Open Source page. This page is about the code that has to come along.

Integrations with ERP, PIM and shipping

An integration is decided by the question of direction: which system holds the master data for products, prices, stock, customers and orders, and which one only reads? Once that is settled field by field, the technology is craft. Magento provides the Commerce Web API for this, as a REST and a GraphQL interface, both available in Magento Open Source. We mostly use REST for data exchange between systems and GraphQL where a frontend or an app queries specific data. If the ERP offers no interface but exports files, a custom module imports those files, following the same rules for logging and error handling. Which ERP or PIM sits behind it is secondary. The effort lies in the state of the data, not in the protocol.

Large volumes of data do not belong in a single request that runs until something breaks. Magento handles bulk operations through message queues: the REST bulk endpoints, for example, place jobs in a queue that consumers work through, started with bin/magento queue:consumers:start. Magento supports RabbitMQ and ActiveMQ Artemis as brokers; in the 2.4.9 release notes Adobe recommends ActiveMQ Artemis for the long term. Regular synchronisation runs as scheduled jobs via the Magento cron. Every run writes a log, a faulty record ends up on an error list instead of halting the whole sync, and an aborted run can be repeated without creating duplicate data. If the consumers stop, monitoring should be the one to notice, not a customer.

One example from our work is the Magento shop of Manotura GmbH & Co. KG for irrigation technology: sprinkler systems, pipe systems and accessories, a range that can only be filtered sensibly by technical attributes. Product master data, prices and stock come from the ERP, and orders go back to it. The transfers run as scheduled jobs with logging and retry logic, so a single failure does not block the whole sync. More than 12,000 products sit in the synchronised catalogue, prices and stock are reconciled every hour, and maintenance effort is around 40 per cent lower than with double data entry. For shipping, 2.4.9 includes a DHL connection via the MyDHL REST API; other carriers we connect through their own interfaces. Data is maintained in one place, and the shop follows.

B2B in Magento Open Source: custom modules instead of a B2B licence

Adobe's B2B module belongs to Adobe Commerce and, according to Adobe, requires a separate licence. Customer Segments and Content Staging, among others, are also available in Adobe Commerce only. Anyone using Magento Open Source therefore builds B2B features as custom modules — on a foundation that Open Source already provides: customer groups, tier prices, catalogue and cart price rules, multiple websites, stores and store views with their own languages and currencies, plus Inventory Management, which is installed by default. That is more than many expect, and for some B2B shops it is already enough. The rest is development that fits your sales process rather than a ready-made feature bundle. Where an Adobe Commerce licence is already in place, we use the B2B module and extend it where it falls short.

Typical modules we build for B2B on Open Source: prices per customer from the ERP instead of a separate customer group for each customer, company accounts with several buyers and roles, order approvals above a certain value or for specific product groups, budgets per cost centre, quick order by part number and quantity, quote requests from the basket, and a catalogue that shows prices only after a verified registration. If buyers order from a procurement system, an OCI punch-out is added; the basket then goes back into the customer's own system. Each of these features uses the intended extension points — plugins, observers and service contracts — and gets its own tables via declarative schema. We build what your sales team actually needs, not everything a B2B package might contain.

Customer-specific prices have a technical side that is often underestimated. A price that applies to one customer only must not end up in the HTTP cache for everyone, has to be taken into account during indexing and must apply in search, filters and search suggestions just as on the product page. With many customers and frequent price changes, whether prices are calculated in advance or determined on request is an architectural decision with consequences for indexers and page load times. We make it before development starts, based on your numbers of customers, products and price changes. How visibility rules and customer prices apply in shop search is covered on our page about shop search with OpenSearch. A business customer will forgive a slow page sooner than a price meant for someone else.

Frontend and performance: theme, Hyvä, indexers, cache

A custom theme inherits from an existing one and overrides specific layout files and templates rather than copying them wholesale. Every overridden file has to be read against the new original at upgrade time, so the number of overrides determines the maintenance cost, not the look. Since 10 November 2025 the Hyvä Theme has been free and open source, under the same licences as Magento Open Source, OSL-3.0 and AFL-3.0. Hyvä UI, Hyvä Checkout and the Hyvä Commerce and Hyvä Enterprise packages remain paid products. Whether Hyvä suits your shop depends less on the theme than on your extensions: every module that brings its own frontend has to work with the chosen theme. We check that before the decision, module by module.

Performance starts with measurement. When category and product pages are slow, the cause is rarely the hardware and usually indexers, cache and modules. Indexers keep calculated data such as prices, category assignments and stock up to date; bin/magento indexer:reindex rebuilds them once, but they stay current only with a working cron. In front sits Varnish as the HTTP cache, serving finished pages without starting PHP — as long as no module needlessly marks a page as uncacheable. Valkey handles cache and sessions, and message queue consumers process background tasks. If one of these components fails or is misconfigured, the whole shop slows down, and the symptom rarely points to the cause.

So we first look for the place where the time is lost: in the database, in a plugin that makes an external request for every product, in a template, in an indexer that lags behind, or in search. Search and filters with OpenSearch have a page of their own; here the subject is the code. In production mode, set with bin/magento deploy:mode:set production, compilation and static content deployment run as part of the switch; a live shop left in developer mode wastes time on every request. Running the services behind it — servers, Varnish, Valkey, OpenSearch, staging — is described on our Magento Open Source page. An optimisation nobody has measured is a guess with an invoice.

Process

The code first, then the quote.

Send us a few sentences about your project: which module, integration or B2B feature, which Magento version is running today and which extensions are installed. You get an initial assessment with no obligation: how it can be implemented cleanly and what the effort depends on in your case. Phone +49 441 21 21 63 0, Mon–Thu 9:00–16:00, Fri 9:00–13:00 (CET). We work remotely across Germany, with meetings in Oldenburg and the north-west by arrangement.

  1. 01

    Initial conversation and assessment

    You describe the project: a new module, an integration, a B2B feature, taking over existing code or a shop that has become slow. We tell you whether and how it can be implemented cleanly in Magento — with no obligation and before any quote is discussed.

  2. 02

    Code review

    We look into modules, extensions, configuration and integrations, run the Coding Standard and the compiler and search for core changes. The result is a written report covering risks, sequence and effort in person-days.

  3. 03

    Concept and quote

    You receive a feature list with a decision for each item: standard, extension, custom module or leave out. For integrations it states which system owns each field, plus the effort in person-days per item and a schedule. Clearly defined parts we offer at a fixed price.

  4. 04

    Development on the staging system

    Development happens in custom modules, versioned in a Git repository that belongs to you, and deployed to a staging system with a copy of the live data. You approve on the running system, not on screenshots.

  5. 05

    Testing and acceptance

    Integrations go through trial runs with logging and reconciliation against the leading system, B2B features are tested with test accounts per customer group, and load times are measured before and after the change. The Coding Standard and compilation run without errors.

  6. 06

    Deployment and operation

    Deployment runs through Composer and bin/magento in the agreed maintenance window, with a backup beforehand. After that we run and maintain the shop on our servers in Germany, with a service level agreement if you wish, and keep developing it.

Projects on this system

A selection — not the full client list.

Frequently asked questions

What does developing a Magento module cost?

That depends on the scope of the module and on the code it has to fit into, which is why we do not offer package prices. A module that adds one function at a clearly defined point is a different order of magnitude from an ERP integration with bulk data or a B2B module with approvals and customer prices. We estimate in person-days, with separate items for concept, development, testing and deployment. For existing shops a code review comes first, because third-party extensions and core changes often determine the effort more than the new feature does. We quote a price after the review or concept, and the hourly rate on request.

Why no changes to the Magento core?

Because a change to the core is lost at the next upgrade or blocks it. Composer installs Magento and its packages into the vendor directory and rewrites the original files during an update; a line changed there simply disappears. Magento provides proper ways to intervene: plugins before, after or around public methods, observers on events and, where necessary, a preference via di.xml. These interventions live in custom modules, are traceable and can be checked specifically at upgrade time. A core change saves hours during the build and costs them again at every upgrade.

Do you take over Magento code and extensions from other agencies?

Yes, that is the most common case. It starts with an inventory of every module: origin, maintenance status, plugins and preferences, clashes with other modules, changes to the core. The Coding Standard and the compiler run over the code, and on a staging system with your data we see what actually happens. We then decide per module whether it stays, is updated, replaced, rebuilt or removed. Access to the repository, servers and Marketplace account is clarified beforehand, not during an incident. Everything we find goes into a written report — including what has been done well.

Will our extensions still work after upgrading to Magento 2.4.9?

That can only be answered extension by extension, but 2.4.9 brings changes that affect many modules. Adobe replaced Zend_Cache with symfony/cache and Laminas MVC with its own MVC implementation, raised the Symfony dependencies to 7.4 LTS and replaced TinyMCE with HugeRTE; the approved PHP version is 8.5. According to Adobe, extensions that use Zend_Cache must be adapted. We test every extension on a staging system running 2.4.9, adapt custom and inherited modules and check with the vendors of purchased extensions whether a compatible version is available. The upgrade process itself is described on our Magento Open Source page.

Is the Upgrade Compatibility Tool available for Magento Open Source?

No. According to Adobe, the Upgrade Compatibility Tool is available for Adobe Commerce instances only. For Magento Open Source we therefore check in other ways: with the Magento Coding Standard via PHP_CodeSniffer, with bin/magento setup:di:compile, which brings errors in dependencies and generated code to light early, with existing tests and with a complete run on a staging system holding a copy of the live data. We also read the list of backward-incompatible changes that Adobe publishes against the custom code. It takes more manual work, but it is no less thorough.

Do we need Adobe Commerce for a B2B shop?

No, B2B shops can be built on Magento Open Source as well; only the ready-made B2B module belongs to Adobe Commerce and requires a separate licence. Open Source includes customer groups, tier prices, catalogue and cart price rules, and multiple stores, languages and currencies. Anything beyond that — prices per customer from the ERP, company accounts, approvals, quick order, punch-out — is built as a custom module, tailored to your processes. Whether that costs less than a licence, we calculate over the full term. Where an Adobe Commerce licence is already in place, we use the B2B module and extend it where it falls short.

How do you connect an ERP or PIM to Magento?

Through Magento's Web API, REST or GraphQL, and for bulk data through message queues — once it is settled which system owns which data. Regular synchronisation runs as scheduled jobs: every run writes a log, faulty records go onto an error list, and an aborted run can be repeated without creating duplicate data. If the ERP only exports files, a custom module imports them under the same rules. At Manotura, more than 12,000 products with prices and stock reconciled every hour come from the ERP this way, and orders go back. Which ERP sits behind it is secondary; what matters is the state of the data.

REST or GraphQL — which do you use for what?

We mostly use REST for exchange between systems and GraphQL mainly where a frontend or an app queries specific data. Both are part of the Commerce Web API and are available in Magento Open Source. For bulk operations REST offers bulk endpoints that process jobs through a message queue, which suits ERP and PIM synchronisation. GraphQL returns exactly the fields a page needs and, since 2.4.9, sets limits on aliases and query length. We build custom endpoints on service contracts, so the same logic is reachable through both routes and does not have to be written twice.

Is Hyvä worth it for our Magento shop?

That depends mainly on your extensions, less on the theme. Since 10 November 2025 the Hyvä Theme has been free and open source, under OSL-3.0 and AFL-3.0, so licence costs for the theme itself are no longer an argument. Hyvä UI, Hyvä Checkout and the Hyvä Commerce and Hyvä Enterprise packages remain paid. Every module that brings its own frontend has to work with the theme; otherwise it is adapted or replaced. We check that module by module before you decide and state the effort in person-days. Changing the theme is a project, not a switch.

Why is our Magento shop slow?

Usually because of indexers, cache or individual modules, rarely because the servers are too small. Indexers stay current only with a working cron, Varnish helps only if pages are cacheable, and message queue consumers have to be running or background tasks pile up. Add plugins that make external requests on every page view, templates with expensive loops and shops running in developer mode instead of production mode. We first measure where the time goes and then make targeted changes. Slow search and filters are covered on our page about shop search with OpenSearch. More hardware helps only once the code stops wasting time.

New project: Magento or Shopware 6?

Magento fits when large catalogues, many variants, several stores, languages and currencies or a lot of custom business logic come together, often in B2B. For projects like that we also build new shops on Magento Open Source, with no licence fees and run on our own servers in Germany. For a mid-sized range with moderate custom logic, Shopware 6 is often the more economical choice — cheaper to run and closer to the German market. We deliver that too, as well as migrations from Magento to Shopware 6. Which route fits we work out in the first conversation, based on your range and your processes, not on a preference.

Who owns the code, and who looks after the shop afterwards?

You own the code: custom modules sit in a Git repository that belongs to you, the domain is always registered in your name, and licences and the Marketplace account are held by your company. Sharpness runs and maintains the shop on its own servers in Germany, optionally with a service level agreement of 24, 8 or 4 hours response time, booked for a year; the work itself is billed by effort or within an agreed framework. Without an SLA we handle requests within 48 hours during business hours, +49 441 21 21 63 0, Mon–Thu 9:00–16:00, Fri 9:00–13:00 (CET). More on operation is on our Magento Open Source page.

Enquiry

What should your Magento shop be able to do?

A few sentences are enough: the feature, integration or problem, Magento version and edition, key extensions. We get back to you with questions and an initial assessment — with no obligation and before any quote is discussed.

  • An answer from someone who knows the system — no phone queue
  • An assessment before the quote, even when it advises against the project
  • Your details are sent to us by email, not into a third-party CRM

Spam protection: Cloudflare Turnstile — no cookies, no tracking.

Call Start a project