Keeping a Legacy CodeIgniter Application Safe and Maintainable
What it takes to keep a CodeIgniter 3 application running safely: the settings to check today, PHP 8 compatibility, patching weak code, backups, containment, and the signs that it is time to migrate.

Plenty of businesses run on a CodeIgniter 3 application that was finished years ago and has barely been touched since. It works, people depend on it, and a rewrite is not in this year's budget. That is a reasonable position, provided the application is looked after. CodeIgniter maintenance on a legacy system is mostly a short list of unglamorous tasks, and skipping them is what turns an old application into a liability.
This guide goes through those tasks in order of urgency, then describes how to tell when maintaining has stopped being the cheaper option.
Where CodeIgniter 3 stands
The CodeIgniter download page describes version 3 as in maintenance, receiving mostly security updates. At the time of writing its most recent stable release is 3.1.13, and the changelog for the last two releases lists compatibility work for PHP 8.0 and 8.1. Active development happens in CodeIgniter 4, which is a rewrite.
In practice this means the framework will not gain features and will not follow new PHP versions quickly. It does not mean an application on it is unsafe by definition. Most risk in these systems comes from the application code, the server and the configuration, and all three are in your hands.
Establish what is running
- The framework version. Open
system/core/CodeIgniter.phpand read theCI_VERSIONconstant. Anything below the last 3.1 release should be updated first, by replacing thesystemfolder and following the upgrade notes for each version in between. - Whether
system/was edited. Compare it with a clean download of the same version. Changes made directly to framework files disappear on update, so each one has to be found and moved intoapplication/coreor documented as a patch. - The PHP version, for the web server and for cron separately.
- Third-party code: everything in
application/librariesandapplication/third_party, plus JavaScript libraries, with versions. - Where the code lives. If the only copy is on the server, put it into version control before changing anything.
Settings to check today
CodeIgniter 3 ships with defaults that suit a developer's laptop. Many production applications still run with them.
| Setting | Where | Default | Production value |
|---|---|---|---|
ENVIRONMENT | index.php, or the CI_ENV server variable | development | production, which stops PHP errors from being shown to visitors |
csrf_protection | application/config/config.php | FALSE | TRUE, after checking that forms use form_open() and AJAX calls send the token |
cookie_secure, cookie_httponly | config.php | FALSE | TRUE on an HTTPS site |
sess_regenerate_destroy | config.php | FALSE | TRUE, so old session IDs stop working |
log_threshold | config.php | 0 (no logging) | 1, so errors are written to application/logs |
db_debug | application/config/database.php | Off only in production | FALSE. Older projects have it hard-coded to TRUE, which prints failed SQL to the screen |
Check the folder layout too. The application and system folders are protected by .htaccess files, which only Apache reads. On nginx, deny access to both in the server configuration, or move them above the web root as the CodeIgniter documentation recommends.
Running CodeIgniter 3 on a supported PHP version
An application on PHP 5.6 or 7.x runs on an interpreter that no longer gets security fixes, and that outweighs anything in the framework. The PHP supported versions page shows which branches are still covered. The path that works:
- Update the framework to the last 3.1 release, which is where the PHP 8 fixes are.
- If
database.phpstill names themysqldriver, change it tomysqli. The old extension no longer exists. - Run the application on PHP 8 in a staging copy with
ENVIRONMENTset todevelopmentandlog_thresholdat its highest, and work through what appears.
Most of what appears will be your own code: null passed to string functions, loose comparisons, removed functions in old libraries. On PHP 8.2 and later you will also see deprecation notices about dynamic properties, from your classes and from the framework's own. Declare the properties in your code. For classes that receive properties by design, which includes controllers because the loader attaches libraries and models to them, PHP provides an attribute:
#[AllowDynamicProperties]
class MY_Controller extends CI_Controller
{
}
Child classes inherit the attribute, and older PHP versions read the line as a comment. Where the notice comes from a core class, apply the same attribute there and record it as a patch to system/ in version control. These are deprecations and not failures today, but they show the direction: each new PHP release takes more effort. The general method is in our guide to upgrading a legacy PHP application.
Patch the code the framework cannot protect
The framework has safe tools. Legacy code often goes around them. Four searches find most problems:
- SQL built from strings. Search for
->query(with variables inside the SQL. Query Builder calls escape values for you, and raw queries should use bindings. - Unescaped output. Views that echo database or request values need
html_escape(). The oldglobal_xss_filteringoption is deprecated and was never a substitute for escaping output. - Password storage. Any
md5()orsha1()near the login code should move topassword_hash(), rehashing each user at their next login. - Uploads and old libraries. Upload folders inside the web root must not execute PHP, and bundled editors, file managers and mail or PDF libraries need updating or removing.
// Before: request data concatenated into SQL
$query = $this->db->query("SELECT * FROM orders WHERE ref = '" . $ref . "'");
// After: query bindings
$query = $this->db->query('SELECT * FROM orders WHERE ref = ?', array($ref));
Then check access control by hand. Log in as an ordinary user and request an admin address directly. In applications where each controller method is reachable by its address, a missing login check in one constructor exposes everything in that controller.
Backups, staging and version control
A legacy application needs three things before anyone changes it: a backup that has been restored at least once, a staging copy, and a repository. The backup covers the database, the uploaded files and the code including system/, and it is stored away from the web server. The staging copy runs on the same PHP version as production with a recent copy of the data. With those in place a fix becomes a small, reversible step, and work that used to feel dangerous becomes routine.
Contain what you cannot fix yet
Some weaknesses take months to remove. Until then, reduce what an attacker can reach:
- Restrict the admin area to known IP addresses or a VPN, and rate limit the login address at the web server.
- Give the application's database user rights on its own schema only.
- Make the code directories read-only for the web server user. Only uploads, cache, logs and sessions need to be writable.
- Delete controllers, test scripts and old modules that nobody uses. Code that is gone cannot be exploited.
- Put a web application firewall or a filtering reverse proxy in front as an extra layer, not as the fix.
A monthly CodeIgniter maintenance routine
- Read the files in
application/logsand the PHP error log, and fix what repeats. - Apply operating system and PHP patch releases on staging, test login and the main workflows, then apply them to production.
- Confirm that backups ran, and restore one every quarter.
- Review the list of admin users and remove accounts of people who have left.
- Check certificate expiry, disk space and that scheduled jobs still run.
- Note every change in the repository, so the next developer can see what was done and why.
When maintaining stops being the cheaper option
Staying on CodeIgniter 3 is a decision to revisit every year. It is time to plan a move when the PHP version you need next produces more work than the last one did, when a library you depend on has been abandoned, when new features need things the framework lacks such as queues or a modern API layer, when a customer's security review asks about framework support, or when it gets hard to find developers willing to work on it. The usual routes are a conversion to CodeIgniter 4, covered in what changes between CodeIgniter 3 and 4, or a rebuild on another framework.
If you have a developer who knows the application, the tasks above are within reach in-house. If the original developers are gone and nobody is sure what the code does, start with an audit. We take over systems like this under CodeIgniter maintenance and support, continue CodeIgniter 3 development where the business needs changes now, and plan the CodeIgniter 3 to 4 upgrade when the time comes.
Frequently asked questions
Is CodeIgniter 3 still supported?
It is in maintenance. The project describes it as receiving mostly security updates, and new development goes into CodeIgniter 4. You can keep running it, but you should not expect it to follow new PHP versions promptly.
Does CodeIgniter 3 run on PHP 8?
Yes, from release 3.1.12 onward, whose changelog lists PHP 8.0 and 8.1 compatibility. On newer PHP versions it runs with deprecation notices that you manage as described above. Your own application code usually needs more changes than the framework does.
Is it safe to keep a CodeIgniter 3 application in production?
It can be, if it runs on a supported PHP version, the production settings are correct, the code has been reviewed for injection and access control problems, and someone applies patches and reads the logs. An unmaintained application on an old PHP version is not safe, whatever framework it uses.
Should we move to CodeIgniter 4 or to Laravel?
CodeIgniter 4 keeps the concepts your team knows and is the shorter conversion. Laravel is a larger rebuild that brings queues, a richer data layer and a bigger hiring pool. The right choice depends on where the product is going, and both are easier from a well-maintained version 3 codebase.
Add worldwincoder.com as a preferred source on Google, or open this article in your AI assistant to use it as a source.
