Magento 2: practical explanation of what is a proxy class?

This particular usage is not a good example of using Proxy pattern. I think it is even useless in that particular piece of code, as a collection is not doing any DB operations unless load method is called. If their observer would be used in console command class as the dependency, then it makes sense to use a proxy.

The proxy class should only be used when during construction of the object you execute an expensive operation. A good example is Symfony console commands:

Imagine your console command is using ProductRepository as a dependency. Product repository constructor establishes MySQL connection to catalog database.

It means on every bin/magento call, no matter which command you execute, the repository dependencies will be instantiated. So the only way to avoid it is to use lazy instantiation of original object by creating a proxy. In this case database, connection to catalog database will be established only when you call a repository method.

Hope that helps to understand the idea of proxy better.


A proxy class lets you dependency-inject a class that you won't necessarily need, and that has a high cost associated with doing so.

If you look at a proxy Magento has generated, like \Magento\Framework\View\Layout\Proxy, you'll see it has all of the same methods as the original class. The difference is that every time any of those are called, it checks if the class it's a proxy of has actually been instantiated, and creates the object if not. (This happens in a _getSubject() or _getCache() method.)

It's lazy loading for dependency injection.

You should use a proxy if a class dependency is not always used by your class, and:

  • Has a lot of dependencies of its own, or
  • Its constructor involves resource-intensive code, or
  • Injecting it has side effects

One good example of this is sessions. Getting sessions through the ObjectManager is bad practice, but injecting a session class like \Magento\Customer\Model\Session could break things if your class ever runs outside of that session's scope (say you inject the frontend customer session on an admin page). You get around that by injecting the session's proxy \Magento\Customer\Model\Session\Proxy instead, and only referencing it when you know it's valid. Unless you reference it, the session is never instantiated, and nothing breaks.

In your specific example of di.xml, it looks like they used the proxy to justify injecting a controller rather than that controller's factory. Either way, that is not what proxies are intended to be used for, and the benefit of it in that situation is likely minimal.


Magento 2 type autogenerated proxies can be used to "fix" design mistakes. That can be very handy. There are 2 use cases:

  1. Wrap an expensive object graph that might not be needed every time by the dependee.

  2. Break a cyclic dependency where class A depends on B and class B depends an A.
    Injecting B\Proxy into A lets you instantiate A, which then in turn can be used to instantiate B when it is actually used with the real A object.

In case of 1. the dependency that isn't always used is a sign that the dependee class does to much, or maybe does to much by one method. The console command @ivan mentioned are a good example of that.

In case of 2. I don't know a generic way to break up that dependency. I tend to rewrite if there is time, but that might not be an option.

Just as a side note, I would like to add that there are many more types of proxies in OOP than the autogenerated lazy instantiation one Magento 2 uses (e.g. remote proxy).